Skip to content

Sprzątanie ostrzeżeń z pytest (Py3.13 / Django 5.2 LTS)#152

Merged
mpasternak merged 15 commits into
devfrom
fix/cleanup-test-warnings
Apr 19, 2026
Merged

Sprzątanie ostrzeżeń z pytest (Py3.13 / Django 5.2 LTS)#152
mpasternak merged 15 commits into
devfrom
fix/cleanup-test-warnings

Conversation

@mpasternak
Copy link
Copy Markdown
Member

Summary

Zbiorczy porządek 17 grup ostrzeżeń, które pokazywały się w pełnym runie pytest (log /tmp/bpp-after-fixes.log, Py 3.13 + Django 5.2). Po tych 16 commitach wszystkie kategorie są zamknięte — albo naprawione w kodzie / zależnościach, albo zgłoszone upstream z targetowanym filtrem w pytest.ini.

Zrobione w tym PR

Grupy wg oryginalnego numerowania z audytu:

  • [1] naive datetime → timezone.now() w produkcji (bpp/util.py, bpp/admin/templates.py, ewaluacja_optymalizacja/tasks, ...). 1df67bdd
  • [2] Constance sync-in-async → get_values_for_keys w context processor zamiast getattr(config, X). eb9f30d5
  • [3] UnorderedObjectListWarning → stabilne order_by w autocomplete, pbn_wysylka_oswiadczen, RaportSlotowUczelnia, RozbieznosciView. 1a372897
  • [4] PBNClient.get_page "did not return a paged resource" — fix w mockach testowych (wrap w pbn_pageable_json), kod produkcyjny bez zmian. be63367d
  • [5] PytestAssertRewriteWarning — przywrócony pytest_plugins w top-level conftest.py + fixtures.const zamiast eager from .conftest_X import *. ce9b9588
  • [6] @pytest.mark.* nałożone na fixture → usunięte. 0f624d26
  • [9] Meta.model mismatch w tabelach django-tables2 → wyrównane. d9aed17b
  • [12] openpyxl cell.font.copy()Font(...). ad33697f
  • [13] wydawnictwo= setter → wydawca_opis= w testach. 73f0bce9
  • [14] itertools.count w CounterMixin (django-flexible-reports) → bump 0.2.12 + release na PyPI, bump zależności. b58c4bc6
  • [15] create_test_db/tests.py — pytest-style. 9efa97c9
  • [16] wait_for_object → celery retry zamiast time.sleep(10). d0948c6f
  • [17] TestReport rejestrowany 2× → przeniesiony do test_bpp app z migracją. 89436d43
  • [10]/[11] zewnętrzne utcnow i findAll — bump MOAI-iplweb 2.0.1 (fix upstream), filter w pytest.ini dla pyoai i webtest. Dodatkowo otwarty PR upstream infrae/pyoai#61. 8b0737b8
  • [8] get_joining_columns deprecation → fix upstream w django-denorm-iplweb 1.10.2 + release na PyPI + bump zależności. 4b6af418

Tylko grupa [7] (FORMS_URLFIELD_ASSUME_HTTPS) była na gałęzi feature/django-5.2 — zamknięta wcześniej tam (4d44441e), nie ma jej w tym PR.

Test plan

  • uv run pytest src/long_running/ src/integrator2/tests/test_tasks.py src/pbn_export_queue/tests/test_tasks.py — 54 passed, 0 warningów Ta funkcja niepotrzebnie.
  • uv run pytest src/pbn_api/tests/test_client_sync.py src/pbn_api/tests/test_client_helpers.py src/pbn_api/tests/test_bpp_admin_helpers.py src/bpp/tests/test_views/test_api.py -W "error:did not return a paged resource:RuntimeWarning" — 44 passed.
  • uv run pytest src/ewaluacja_optymalizacja/tests/test_discipline_pins.py::test_reset_discipline_pins_no_unpinned_shows_warning src/import_dyscyplin/tests/test_views.py::{test_CreateImport_DyscyplinView_bledny_plik,test_CreateImport_DyscyplinView_dobry_plik,test_UsunImport_Dyscyplin} -W "error:Synchronous access to Constance:RuntimeWarning" — 4 passed.
  • uv run pytest src/raport_slotow/tests/test_views/test_raport_slotow_uczelnia.py src/raport_slotow/tests/test_views/test_uczelnia.py src/ranking_autorow/tests.py -W "error:Table data is of type:UserWarning" — 31 passed.
  • uv run pytest src/bpp/tests/test_autocomplete/test_autocomplete_security.py ... -W "error::django.core.paginator.UnorderedObjectListWarning" — 106 passed.
  • uv run pytest src/bpp/tests/test_views/test_oai.py -W "error:The usage of get_joining_columns:DeprecationWarning" — 6 passed.
  • Pełny run CI

Dependencies bumped

  • django-flexible-reports 0.2.11 → 0.2.12 (PyPI, własny fork)
  • MOAI-iplweb ==2.0.0 → >=2.0.1 (PyPI, własny fork — wymusił downgrade sqlalchemy 2.x → 1.4 i setuptools 80 → 79 przez transitive constraints)
  • django-denorm-iplweb >=1.10.1 → >=1.10.2 (PyPI, własny fork)

Upstream kontrybucje

  • infrae/pyoai#61 — fix datetime.utcnow(); do czasu mergea filter w pytest.ini.

🤖 Generated with Claude Code

mpasternak and others added 15 commits April 19, 2026 21:17
Zamiana datetime.now() → timezone.now() w miejscach, gdzie wartość
trafiała do pola DateTimeField (zapis lub filtr). Przy USE_TZ=True
Django emitowało RuntimeWarning "received a naive datetime" i
interpretowało wartość w lokalnej strefie czasowej, co przy DST
mogło powodować niespójności dat w bazie.

- bpp.util.remove_old_objects (uzywane przez oswiadczenia,
  integrator2)
- bpp.admin.templates.TemplateAdmin.template_updated filtr
- ewaluacja_optymalizacja.tasks.optimization OptimizationRun
  .finished_at (3 miejsca)
- ewaluacja_optymalizacja management commands solve_uczelnia,
  solve_evaluation

Testowe literaly "2023-01-01 00:00:00" w pbn_export_queue
zamienione na timezone.make_aware(datetime(...)).

test_OstatnioZmieniony: datetime.now() -> timezone.now().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pytest ostrzegał PytestRemovedIn9Warning "Marks applied to fixtures
have no effect" (49 wystąpień w logach). Markery na fixturach i tak
nie mają efektu — dostęp do bazy dziedziczy się z testu wywołującego,
który ma własny @pytest.mark.django_db. W pytest 9 bedzie to blad.

Dotyczy 7 fixtur w:
- src/conftest.py
- src/import_polon/tests/conftest.py
- src/bpp/tests/test_models/test_sloty/conftest.py

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Zgodnie z konwencja projektu (CLAUDE.md: "NEVER create
unittest.TestCase tests") — zamiana TestCase na zwykla funkcje
pytest. Usuniecie return True eliminuje DeprecationWarning
"It is deprecated to return a value that is not None from a test case".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
openpyxl deprecated StyleProxy.copy() method — used Font() konstruktor
z przepisanymi atrybutami zachowujacymi istniejace wartosci name/size
i doklada bold=True.

Eliminuje DeprecationWarning "Call to deprecated function copy" w
pbn_wysylka_oswiadczen xlsx export.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…etter

Wydawnictwo_Zwarte.wydawnictwo to property z deprekacja, ktore
emituje DeprecationWarning "W przyszlosci uzyj wydawca_opis" przy
zapisie. Zamiana w 2 testach (test_cache.py, test_history.py) na
bezposrednie ustawianie wydawca_opis.

Przy okazji ruff isort uporzadkowal importy w test_history.py.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Definiowanie `class TestReport(Report)` w ciele fixture'a powodowało
ponowną rejestrację modelu `long_running.testreport` przy każdym
uruchomieniu testu korzystającego z fixture'a `report`, co Django
sygnalizowało `RuntimeWarning: Model 'long_running.testreport' was
already registered. Reloading models is not advised...`.

TestReport ma teraz stałą definicję w `test_bpp.models` wraz z
migracją `0003_testreport`, a fixture sprowadza się do prostego
`baker.make(TestReport)`. Nieużywany nigdzie override
`send_notification` (dziedziczony NullNotificationMixin i tak jest
no-opem) został usunięty.
django-tables2 emits `UserWarning: Table data is of type <X> but <Y>
is specified in Table.Meta.model` when the declared Meta.model does
not match the row type of the queryset backing the table. `Meta.model`
is only used for field introspection, so the mismatch was cosmetic —
fix it by pointing it at the actual row type:

- RankingAutorowTable: Autor -> Sumy (queryset is Sumy.objects...)
- RaportSlotowUczelniaTable: Cache_Punktacja_Autora_Query ->
  RaportSlotowUczelniaWiersz (list view iterates over
  raportslotowuczelniawiersz_set)

Drop now-unused `Autor` / `Cache_Punktacja_Autora_Query` imports.
Django emits `UnorderedObjectListWarning` and may serve duplicate or
missing rows across pages when a Paginator is handed an unordered
queryset. Fix the callers surfaced by the current test run:

Autocomplete (bpp.views.autocomplete):
- Dyscyplina_NaukowaAutocomplete — order by (kod, nazwa)
- Wydawnictwo_NadrzedneAutocomplete + admin variants — order by
  (tytul_oryginalny, pk)
- PublicZrodloAutocomplete / ZrodloAutocomplete — order by
  (nazwa, pk); apply to both the base queryset and the
  QuerySetSequence combining PBN-priority branches

Paginated list views:
- pbn_wysylka_oswiadczen.PublicationListView — order the combined
  QuerySetSequence by (-rok, tytul_oryginalny, pk)
- RaportSlotowUczelnia.get_details_set — order raportslotowuczelnia
  wiersz_set by (autor__nazwisko, autor__imiona, pk)

Model Meta:
- RozbieznosciView — restore `ordering = ["id"]` that the abstract
  base had but the concrete Meta was silently overriding. New
  migration 0021 is pure AlterModelOptions (managed=False, no DDL).

Pre-existing ruff findings in raport_slotow/models/uczelnia.py (C901,
unused loop variable) silenced without refactoring — scope is the
pagination fix, not `create_report` internals.
Dotychczas funkcja blokowała workera 10× `time.sleep(1)` czekając, aż
obiekt utworzony w innej transakcji pojawi się w bazie. Teraz w razie
`DoesNotExist` woła `current_task.retry(countdown=1,
max_retries=no_tries)` — celery ponownie uruchomi to samo zadanie za
sekundę, a worker w tym czasie obsługuje inne zadania. Po wyczerpaniu
prób celery podnosi oryginalny `DoesNotExist` (kontrakt
`Task.retry(exc=...)`).

Usunięto `DeprecationWarning` emitowany przy każdym wywołaniu.

Kontrakt: funkcję wywołujemy wyłącznie z kontekstu zadania celery
(`.delay(...)`, `.apply_async(...)`, `.apply(...)`). Wywołanie
funkcji-zadania wprost nie ustawia `current_task` i omija retry.

Testy `analyze_file` i `task_sprobuj_wyslac_do_pbn` przerobione z
bezpośredniego wywołania na wywołanie przez celery. Tam gdzie test
mockuje `task.apply_async` (do weryfikacji re-schedulowania w
gałęziach RETRY_*) używam `task.apply(args=(...)).get()` zamiast
`.delay(...).get()` — `.delay()` trafiłoby w mock apply_async i body
zadania nigdy by się nie uruchomiło.

Dodano trzy testy pokrywające kontrakt `wait_for_object` w
`src/long_running/tests/test_util.py` (happy path, exhaust,
succeed-on-retry). Używają `.apply(throw=False)` + fixture, która
tymczasowo ustawia `app.conf.task_eager_propagates=False`, bo
CELERY_EAGER_PROPAGATES_EXCEPTIONS=True w bpp sprawia, że `Retry`
propaguje się poza `apply()` natychmiast i rekurencyjne
`retval.sig.apply(retries=retries+1)` w `Task.apply` gubi
`throw=False` (używa defaultu z app.conf). Produkcyjny worker tej
fixture nie wymaga.
…ync warnings

Od django-constance 4.x Config.__getattr__ wykrywa aktywną pętlę
asyncio i zwraca AsyncValueProxy zamiast wartości. Django test client
w nowszych wersjach startuje pętlę wewnętrznie, więc stringifikacja
takiego proxy w szablonie (np. {{ WYDRUK_MARGINES_GORA|default:"2cm"
}} w bare.html) emitowała:

  RuntimeWarning: Synchronous access to Constance setting
  'WYDRUK_MARGINES_*' inside an async loop. Use
  'await config.WYDRUK_MARGINES_*' instead.

constance.utils.get_values_for_keys(keys) idzie prosto do backendu
(config._backend.mget) pomijając __getattr__ — bez detekcji pętli,
bez proxy, bez warningu. Działa identycznie w trybie sync i async.

Dotyczyło 4 testów:
- ewaluacja_optymalizacja/tests/test_discipline_pins.py
  ::test_reset_discipline_pins_no_unpinned_shows_warning
- import_dyscyplin/tests/test_views.py
  ::test_CreateImport_DyscyplinView_bledny_plik
  ::test_CreateImport_DyscyplinView_dobry_plik
  ::test_UsunImport_Dyscyplin
Produkcja — `search_publications`, `get_institution_publication_v2`,
`get_institution_statements_of_single_publication` — uderza w
paginowane endpointy PBN i używa `post_pages`/`get_pages`, czyli
oczekuje odpowiedzi o strukturze `{content, pageable, number,
totalElements, totalPages, ...}`. Te funkcje są POPRAWNE.

Mocki w testach zwracały płaską listę (albo `[]`), co w
`transport._pages` odpalało RuntimeWarning:

  PBNClient.{get,post}_page request for ... did not return a paged
  resource, maybe use PBNClient.{get,post} (without 'page') instead

Warning dotyczył 4 plików testowych (test_client_sync,
test_client_helpers, test_bpp_admin_helpers, test_views/test_api).

Owinąłem ok. 30 mocków w istniejący już helper
`fixtures.pbn_api.pbn_pageable_json(content)`. Produkcyjnego kodu
nie ruszam — był poprawny, to mocki nie odwzorowywały rzeczywistego
kształtu odpowiedzi.
W poprzednim refaktorze (commit 057f291 "Duże pliki na małe")
deklaracja `pytest_plugins` została USUNIĘTA z
`src/fixtures/conftest.py` z notatką "moved to top-level
conftest.py (per pytest requirements)" — ale nigdy nie została do
top-level conftest dodana. Dodatkowo `fixtures/__init__.py` robiło
`from .conftest_X import *` dla wszystkich 5 modułów, więc każdy
`from fixtures import …` (np. `from fixtures.playwright_fixtures
import …` w `src/conftest.py:419`) pociągał je w całości PRZED
pytestem. Przy rejestracji jako pluginy pytest już widział je w
sys.modules → 85 ostrzeżeń:

  PytestAssertRewriteWarning: Module already imported so cannot be
  rewritten; fixtures.conftest_{models,publications,system,browser,
  disciplines}

Fix:

- Dodaję `pytest_plugins = [...]` w top-level `src/conftest.py`
  (5 modułów conftest_*). Kolejność deklaracji wewnątrz modułu
  nie ma znaczenia — pytest czyta atrybut po pełnym załadowaniu.
- `fixtures/__init__.py` NIE importuje już conftest_*, tylko
  `fixtures.const`, `fixtures.pbn_api`, `fixtures.wydawnictwa` —
  moduły, które nie są pytest plugins, więc eager import ich
  nie psuje.
- Stałe modułowe `NORMAL_DJANGO_USER_{LOGIN,PASSWORD}` i
  `JEDNOSTKA_{UCZELNI,PODRZEDNA}` przeniesione z conftest_browser /
  conftest_models do nowego `fixtures/const.py`. conftest_X
  importuje je stamtąd; `fixtures/__init__.py` re-eksportuje przez
  `from .const import *`.

Jednocześnie naprawiam regresję z commita `1a372897` (grupa [3] —
UnorderedObjectListWarning): `.order_by("nazwa", "pk")` na
`QuerySetSequence` w `ZrodloAutocomplete.get_queryset()` propagowało
się do sliced sub-queryset (`qs.filter(...)[:10]`), co od Django
4.x zgłasza `TypeError: Cannot reorder a query once a slice has
been taken`. Bazowy queryset `_get_base_queryset` już ma
.order_by, więc każdy slice ma porządek — wystarcza; kolejność
między gałęziami PBN jest priorytetowa (intencjonalnie, nie
alfabetyczna).
…r pyoai/webtest

MOAI-iplweb 2.0.1 (upstream fork by same author) naprawia
datetime.utcnow() -> datetime.now(UTC). Zniknął warning z
moai/oai.py. Downgrade tranzytywny sqlalchemy 2.x -> 1.4 i
setuptools 80 -> 79 wymuszony przez moai-iplweb 2.0.1 constraints
(sqlalchemy<2, setuptools<80).

Dla dwóch pozostałych zewnętrznych warningów bez lokalnego forka
(grupy [10] i [11] TODO) dodałem targetowane filtry w pytest.ini:
pyoai 2.5.0 (oaipmh.server) - datetime.utcnow, webtest 3.0.7
(webtest.forms) - bs4.findAll. Zgłoszenia upstream w toku.
Release 1.10.2 w forku user-a dodaje `get_joining_fields()` do
inline'owej klasy `JoinField` w `TriggerFilterQuery.__init__`
(`denorm/denorms.py:361`). Dzięki temu Django 6.0 przestaje emitować:

  RemovedInDjango60Warning: The usage of get_joining_columns() in
  Join is deprecated. Implement get_joining_fields() instead.

Zweryfikowane przez uruchomienie `src/bpp/tests/test_views/test_oai.py`
z `-W "error:The usage of get_joining_columns:DeprecationWarning"`
— 6 passed, 0 warningów.
@mpasternak mpasternak force-pushed the fix/cleanup-test-warnings branch from 4b6af41 to 1fff2f0 Compare April 19, 2026 19:18
@mpasternak mpasternak merged commit 15f97bc into dev Apr 19, 2026
8 of 9 checks passed
@mpasternak mpasternak deleted the fix/cleanup-test-warnings branch April 19, 2026 19:42
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