Skip to content

fix(bibtex): klucz doktoratu i habilitacji znów zawiera nazwisko autora#676

Open
mpasternak wants to merge 2 commits into
devfrom
fix/bibtex-doktorat-fakeset
Open

fix(bibtex): klucz doktoratu i habilitacji znów zawiera nazwisko autora#676
mpasternak wants to merge 2 commits into
devfrom
fix/bibtex-doktorat-fakeset

Conversation

@mpasternak

Copy link
Copy Markdown
Member

Problem

Praca_Doktorska.autorzy_dla_opisu() zwraca FakeSet — listę udającą
queryset, bo doktorat ma dokładnie jednego autora w polu autor, a nie relację
wiele-do-wielu. FakeSet implementuje all(), select_related(),
exclude(), odpiete_dyscypliny(), exists() — ale nie first().

bpp/export/bibtex.py:93 woła właśnie first():

first_author = wydawnictwo.autorzy_dla_opisu().first()

AttributeError: 'FakeSet' object has no attribute 'first'
(Rollbar #447,
6 wystąpień).

Wyjątek jest tam połykany przez zaloguj_polkniety_wyjatek, więc eksport nie
padał — klucz cichcem gubił nazwisko i zostawało samo <rok>_id<pk>.

Rozwiązanie

FakeSet.first() zwracające pierwszy element albo None.

Testy

Nowy src/bpp/tests/test_export/test_bibtex_klucz_doktoratu.py — TDD, oba
testy najpierw padały ('2020_id…' != 'Kowalski_2020_id…').

  • src/bpp/tests/test_export/ — 39 passed

Uwaga na przyszłość (NIE ruszam w tym PR)

FakeSet.exists() zwraca twarde False, mimo że lista ma jeden element.
To wygląda na celowe (jakiś kod pewnie sprawdza exists(), żeby nie renderować
listy autorów dla doktoratu), ale jest mylące. Zmiana wymagałaby przejrzenia
wszystkich wywołań autorzy_set.exists() — osobny temat.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NcAqeqyqBzNEkkVnhpHDaH

mpasternak and others added 2 commits July 24, 2026 23:58
Praca_Doktorska.autorzy_dla_opisu() zwraca FakeSet — listę udającą queryset,
bo doktorat ma dokładnie jednego autora w polu `autor`, a nie relację M2M.
FakeSet nie miał metody first(), więc generate_bibtex_key leciało na
AttributeError. Wyjątek jest tam połykany (zaloguj_polkniety_wyjatek), więc
eksport nie padał — klucz po prostu gubił nazwisko i zostawało samo
`<rok>_id<pk>`, a do Rollbara szedł item (#447, 6 wystąpień).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NcAqeqyqBzNEkkVnhpHDaH
Self-review słusznie wytknął, że FakeSet.first() naprawia JEDEN z czterech
kształtów zwracanych przez autorzy_dla_opisu(). bpp.models.util zwraca też:
queryset, gołą listę z Prefetch(to_attr=...) oraz [] dla obiektu bez pk.
Żaden z listowych nie ma first(), więc dokładnie ten sam AttributeError
czekał obok — i jest osiągalny: prefetch_dane_strony_rekordu podstawia
listę, a nowy test to potwierdza (padał na 2019_id... zamiast Nowak_2019_id...).

generate_bibtex_key bierze teraz pierwszy element przez ten sam idiom, co
bpp.models.util: first() gdy jest, inaczej next(iter(...), None).

FakeSet.first() zostaje — jest potrzebny — a exists() dostaje komentarz
wyjaśniający, że twarde False NIE jest sprzecznością: exists() jest
osiągalne tylko po exclude(), które w FakeSet ignoruje warunki, więc False
znaczy "brak autorów z odpiętą dyscypliną", nie "brak autorów".

Zgodnie z uwagą review NIE dodaję do_rollbar=False w tym except — po tej
poprawce nadal jest osiągalny (nazwisko None, błędy bazy), a item #447 był
jedynym sygnałem, że coś jest nie tak.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NcAqeqyqBzNEkkVnhpHDaH
@mpasternak

Copy link
Copy Markdown
Member Author

Poprawki po self-review

Review trafnie zauważył, że pierwszy commit naprawiał objaw, nie przyczynę.
Naniesione w a7fa3c56a:

Przyczyna: autorzy_dla_opisu() zwraca cztery różne kształty, a
generate_bibtex_key zakładał queryset dla wszystkich. bpp/models/util.py:138:

kształt ma first()?
queryset (autorzy_set.select_related(...)) tak
[] gdy not self.pk nie
lista z Prefetch(to_attr=PREFETCH_AUTORZY_ATTR) nie
FakeSet doktoratu/habilitacji nie (przed tym PR-em)

Review oceniał ścieżkę listową jako „dziś nieosiągalną, bo dwa widoki się nie
spotykają". Zweryfikowałem — jest osiągalna. Nowy test
test_klucz_bibtex_dziala_gdy_autorzy_sa_zwykla_lista woła
prefetch_dane_strony_rekordu(wyd), asertuje że autorzy_dla_opisu() to
faktycznie list, i padał dokładnie tak samo jak doktorat:

AssertionError: assert '2019_id6388619' == 'Nowak_2019_id6388619'

Czyli dodanie samego FakeSet.first() zostawiłoby tę samą pułapkę obok.
generate_bibtex_key bierze teraz pierwszy element tym samym idiomem, co
bpp/models/util.py:180: first() gdy jest, inaczej next(iter(...), None).

FakeSet.exists() — zostaje False, ale z komentarzem. Review potwierdził
niezależnie to, co podejrzewałem: exists() jest osiągalne wyłącznie po
łańcuchu exclude(...) (Rekord.ma_odpiete_dyscypliny,
src/bpp/models/cache/rekord.py:344), a FakeSet.exclude() ignoruje warunki
i zwraca self. Gdyby exists() zwracało True, doktoraty dostałyby
ma_odpiete_dyscypliny=True i strona rekordu renderowałaby pusty box „odpięte
dyscypliny". Bez komentarza sąsiedztwo działającego first() i twardego
False w exists() czyta się jak sprzeczność.

do_rollbar=False w tym except — celowo NIE dodane. Review ma rację:
blok pozostaje osiągalny (nazwisko NoneTypeError w re.sub, błędy bazy),
a item #447 był jedynym sygnałem, że coś jest nie tak. Hałas usuwamy naprawą
przyczyny, nie zatkaniem czujnika.

40 passed w src/bpp/tests/test_export/.

Do sprawdzenia po deployu

Review słusznie zwraca uwagę, że skoro istniały dwie ścieżki, część z 6 wystąpień
#447 mogła iść z listowej. Po wdrożeniu warto potwierdzić, że item faktycznie
przestał przyrastać — teraz obie ścieżki są pokryte, więc powinien.

Odnotowane, bez zmian

Drugi test (habilitacja) faktycznie przechodzi tą samą ścieżką co doktorat —
Praca_Habilitacyjna dziedziczy Praca_Doktorska_Baza i nie nadpisuje ani
autorzy_set, ani autorzy_dla_opisu. Zostawiam jako tani strażnik przed
przyszłym rozjazdem, ale nie jest to „drugi przypadek".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant