refactor(ewaluacja): okres ewaluacyjny jako jedna stała, nie ~95 literałów#683
Open
mpasternak wants to merge 2 commits into
Open
refactor(ewaluacja): okres ewaluacyjny jako jedna stała, nie ~95 literałów#683mpasternak wants to merge 2 commits into
mpasternak wants to merge 2 commits into
Conversation
Okres 2022-2025 był powielony jako domyślne argumenty w czterech aplikacjach
ewaluacyjnych, w wartościach pola formularza i w NAZWACH funkcji. Zmiana
okresu wymagałaby polowania po repo, a funkcja nazwana
oblicz_liczby_n_dla_ewaluacji_2022_2025 licząca okres 2026-2029 aktywnie
wprowadzałaby w błąd.
OKRES_2022_2025 = (2022, 2025) jako okres nazwany i zamknięty (stare raporty
muszą dać się odtworzyć), OKRES_DOMYSLNY jako wskaźnik na okres bieżący.
ROK_MIN/ROK_MAX wyprowadzone z OKRES_DOMYSLNY, żeby nie mogły znów zdryfować
— ROK_MAX wynosił 2026, choć reszta kodu liczyła do 2025. Jedynym
konsumentem tych stałych jest get_lista_prac(), niewołane produkcyjnie, więc
poprawka nie zmienia niczego dziś, tylko rozbraja pułapkę.
Zero zmian wyników liczbowych — sygnatury pozostają dwuargumentowe, zmienia
się wyłącznie źródło wartości domyślnej. Bez migracji.
Przy okazji ożywiony test_get_lista_prac_zakres_lat: robił pytest.skip
("cache was not properly populated") ZAWSZE, bo tworzył Autor_Dyscyplina bez
rodzaj_autora, więc kalkulator slotów odrzucał autora i cache zostawał pusty.
Asercja nigdy się nie wykonała. Furtka usunięta, asercja wzmocniona z liczby
prac na konkretne lata — sama liczba nie wykryłaby zjechania zakresu o rok.
Literały 2022/2025 w testach zostawione celowo: test ma przypinać jawną
wartość, inaczej przestaje wykrywać przypadkową zmianę okresu.
Refs FD#437
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01McWgJYK4c4GSMdsm6P4oXc
Druga faza centralizacji. Pierwsza objęła domyślne argumenty funkcji i nazwy;
zostawały inline'owe literały w zapytaniach — kategoria groźniejsza, bo po
przestawieniu OKRES_DOMYSLNY liczyłyby po cichu stary okres, bez żadnego
sygnału błędu.
47 miejsc w 17 plikach: filtry ORM (rok__gte/lte i warianty z prefiksami),
stringi DjangoQL w liczbie N, listy i zakresy lat, domyślne argumenty
argparse sterujące realnym UPDATE-em.
lata_okresu() w ewaluacja_common trzyma jedyne "+1" wynikające z tego, że
okres jest przedziałem domkniętym, a range() ma prawy koniec wyłączny — żeby
ta jedynka nie była powtarzana i mylona w każdym miejscu budującym listę lat.
Czyta OKRES_DOMYSLNY przy wywołaniu, nie przy definicji, więc da się ją
podmienić w teście.
tasks/helpers.py miało rok__lt=2026 — jedyne miejsce zapisane "od drugiej
strony"; wyprostowane na rok__lte=OKRES_DOMYSLNY[1], semantycznie identyczne
dla lat całkowitych.
Etykiety UI i nazwy plików eksportu ("liczba_n_ewaluacja_2022_2025.xlsx",
"year_range": "2022-2025") celowo nietknięte — nie liczą źle, a nazwanie ich
wymaga decyzji, jak ma się nazywać nowy okres.
Dwa testy strażnicze podmieniają OKRES_DOMYSLNY przez mock.patch i sprawdzają,
że zapytanie faktycznie filtruje po nowym okresie. Łapią też przypadek, w
którym wartość zostałaby zapieczona w domyślnym argumencie — wtedy patch nie
zadziała. Zweryfikowane mutacyjnie.
223 testy w pięciu aplikacjach ewaluacyjnych. Bez migracji.
Refs FD#437
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01McWgJYK4c4GSMdsm6P4oXc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Po co
Wchodzimy w nowy okres ewaluacyjny (od 2026 r.), ale nie wiadomo jeszcze, czy będzie cztero- czy pięcioletni. Dziś okres 2022–2025 jest powielony w ~95 miejscach w pięciu aplikacjach ewaluacyjnych — jako domyślne argumenty funkcji, inline'owe filtry zapytań, stringi DjangoQL, listy lat, a nawet w nazwach funkcji.
Celem jest doprowadzenie do stanu, w którym przestawienie okresu to zmiana jednej linii, a stare raporty nadal dają się odtworzyć według starych zasad.
To jest refaktor pod przyszłą zmianę, nie sama zmiana. Okres pozostaje 2022–2025, wyniki liczbowe są identyczne, migracji nie ma.
Jak
Okresy mają nazwy, nie tylko wartości. Gdy MEiN ogłosi zasady, dopisujemy nową stałą, a
OKRES_2022_2025zostaje nietknięty — dane policzone pod stare zasady muszą dać się odtworzyć, co było wprost wymaganiem.Dodatkowo
lata_okresu()trzyma jedyne+1wynikające z tego, że okres jest przedziałem domkniętym, arange()ma prawy koniec wyłączny. Ta jedynka była wcześniej powtarzana w kilku miejscach — czyli w kilku miejscach można się było w niej pomylić.Dwie fazy
bf432cb6e— domyślne argumenty i nazwy funkcji22 podstawienia + wartości pola formularza wyjęte z HTML-a do kontekstu widoku. Do tego lata wyjęte z nazw:
oblicz_liczby_n_dla_ewaluacji_2022_2025→oblicz_liczby_n_dla_okresuoblicz_liczbe_n_na_koniec_2025→oblicz_liczbe_n_na_koniec_okresuTo groźniejsze niż zaszyte wartości: funkcja nazwana
..._2022_2025, która po zmianie okresu liczy 2026–2029, aktywnie wprowadza w błąd czytającego kod.519162d14— filtry zapytań47 miejsc w 17 plikach: filtry ORM (
rok__gte/rok__ltei warianty z prefiksami), stringi DjangoQL w liczbie N, listy i zakresy lat, domyślne argumenty argparse sterujące realnymUPDATE-em.To była kategoria o największym ryzyku — po przestawieniu stałej te miejsca dalej liczyłyby stary okres po cichu, bez żadnego sygnału błędu.
Przy okazji:
tasks/helpers.pymiałorok__lt=2026— jedyne miejsce zapisane „od drugiej strony". Wyprostowane narok__lte=OKRES_DOMYSLNY[1]; dla lat całkowitych semantycznie identyczne.Znalezione przy okazji: test, który nigdy się nie wykonał
test_get_lista_prac_zakres_latmiał w środku:i wchodził w tę furtkę zawsze — bo budował
Autor_Dyscyplinabezrodzaj_autora, przez co kalkulator slotów odrzucał autora i cache zostawał pusty. Asercja== 5była martwa od momentu napisania.Furtka usunięta, test ożywiony. Asercja wzmocniona, nie osłabiona: zamiast liczby prac sprawdza konkretne lata (
[2022, 2023, 2024, 2025]), bo sama liczba nie wykryłaby zjechania zakresu o rok — 2023–2026 też daje cztery.Ten test wykrył też realną niespójność:
ROK_MAXwynosił 2026, choć cała reszta kodu ewaluacyjnego liczyła do 2025. Jedynym konsumentem tych stałych jestget_lista_prac(), niewołane produkcyjnie, więc naprawa nie zmienia dziś niczego — rozbraja pułapkę, zanim ktoś tę funkcję podepnie.Czego świadomie NIE ruszam
liczba_n_ewaluacja_2022_2025.xlsx,"year_range": "2022-2025")verbose_name = "Dyscyplina nieraportowana 2022-2025"AlterModelOptions.get_lista_prac()Testy strażnicze
Dwa nowe testy podmieniają
OKRES_DOMYSLNYprzezmock.patchi sprawdzają, że zapytanie faktycznie filtruje po nowym okresie:ewaluacja_liczba_n/tests/test_okres_w_zapytaniach.py— zakłada udziały za oba okresy, patchuje na (2026, 2029), asertuje wynikewaluacja_optymalizacja/tests/test_okres_w_zapytaniach.py—lata_okresu()jako przedział domknięty (błąd o jeden) + filtr przeglądarki publikacjiŁapią też przypadek, w którym wartość zostałaby zapieczona w domyślnym argumencie — wtedy
patchnie zadziała i test padnie. Zweryfikowane mutacyjnie: po cofnięciu zmian do literałów oba padają.Weryfikacja
src/ewaluacja_*makemigrations --check --dry-run→ brak nowych migracjimanage.py checkczystyruff checkiruff format --checkczyste na dotkniętych plikachPełna regresja repo: przerwana na 74%, świadomie. Docker na maszynie deweloperskiej zdegradował się w trakcie sesji (przestał montować pliki z dysku, a baza testowa zaczęła pełzać na
TRUNCATEw oczekiwaniu na I/O — 65 minut na 74% przy 15 minutach dla identycznego przebiegu wcześniej tego samego dnia). To ograniczenie środowiska, nie kodu; pełną regresję zweryfikuje CI.Do momentu przerwania padły 2 testy:
api_v1/tests/test_n_plus_jeden.py::test_praca_doktorska_lista_bez_n_plus_jedeni::test_patent_lista_bez_n_plus_jeden. Zdiagnozowane do końca — to artefakt środowiska deweloperskiego, nie błąd w kodzie:origin/devpadają dokładnie te same dwa (2 failed, 10 passedna obu gałęziach), a ta gałąź nie dotykaapi_v1;devjest zielone, więc w poprawnym środowisku przechodzą;charakter_formalnyjakocached_propertyrobiąceCharakter_Formalny.objects.get(skrot="D"/"PAT"), czyli wymagają słownika z baseline'u. W zastępczej bazie testowej (postawionej ręcznie po awarii Dockera) baseline się nie załadował — sprawdzone:Charakter_Formalny.objects.count() == 1zamiast 27.Nie ma tu nic do naprawienia w repozytorium.
⚠ Konflikt przy scalaniu z PR #682
Ta gałąź i #682 (raport kompletności POL-on) obie dopisują stałe do
src/ewaluacja_common/const.py. Konflikt jest czysto tekstowy, nie logiczny — rozwiązanie brzmi „zachowaj oba dopiski".Stałe są celowo rozdzielne i opisują dwa różne zegary:
OKRES_DOMYSLNY— zakres liczenia punktacji (metryki, liczba N)OKNO_EWALUACJI— zakres obowiązku sprawozdawczego z rozporządzenia POL-onSklejenie ich byłoby błędem: raport POL-on ma patrzeć od 2026 niezależnie od tego, za jakie lata liczone są metryki.
Refs FD#437
🤖 Generated with Claude Code
https://claude.ai/code/session_01McWgJYK4c4GSMdsm6P4oXc