Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,7 @@ opencode.jsonc
dump.rdb
.worktrees/
.claude/

# Local TODO / audit notes (not committed)
TODO-*.txt
TODO-*.md
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies = [
"arrow>=1.3,<2",
"numpy>=2.1.2",
"pygad>=3.6.0",
"django-denorm-iplweb>=1.10.1",
"django-denorm-iplweb>=1.10.2",
"django-tabular-permissions==2.9.3",
"simplejson>=3.19,<4",
"django-reversion>=6,<7",
Expand Down Expand Up @@ -62,7 +62,7 @@ dependencies = [
"django-fsm>=3,<4",
"django-mptt>=0.16,<1",
"wosclient==0.1.5",
"MOAI-iplweb==2.0.0",
"MOAI-iplweb>=2.0.1",
"django_redis==5.3.0",
"django-filter>=25.1,<25.2",
"dbfread>=2.0.7",
Expand Down
6 changes: 6 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ filterwarnings =
# FORMS_URLFIELD_ASSUME_HTTPS is an intentional opt-in for Django 6.0
# behaviour; to be removed together with the setting on 6.0 upgrade.
ignore:.*FORMS_URLFIELD_ASSUME_HTTPS.*:DeprecationWarning
# pyoai 2.5.0 (infrae/pyoai) nadal woła datetime.utcnow()
# w oaipmh/server.py; nie mamy forku — zgłoszenie upstream.
ignore:.*datetime\.datetime\.utcnow.*:DeprecationWarning:oaipmh\.server
# webtest 3.0.7 nadal używa bs4.findAll w forms.py:436 (zamiast
# find_all); nie mamy forku — zgłoszenie upstream (Pylons/webtest).
ignore:.*findAll.*:DeprecationWarning:webtest\.forms

norecursedirs = src/bpp/media/ .worktrees

Expand Down
5 changes: 3 additions & 2 deletions src/bpp/admin/templates.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sys
import traceback
from datetime import datetime, timedelta
from datetime import timedelta

from dbtemplates.admin import TemplateAdmin, TemplateAdminForm
from dbtemplates.models import Template
Expand All @@ -13,6 +13,7 @@
from django.template.loaders.cached import Loader as CachedLoader
from django.template.response import TemplateResponse
from django.urls import re_path as url
from django.utils import timezone

from bpp.util import rebuild_instances_of_models

Expand Down Expand Up @@ -78,7 +79,7 @@ def template_updated(self, request, obj):
return

ILE_DNI = 7
dni_temu = datetime.now() - timedelta(days=ILE_DNI)
dni_temu = timezone.now() - timedelta(days=ILE_DNI)

messages.info(
request,
Expand Down
45 changes: 28 additions & 17 deletions src/bpp/context_processors/constance_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,47 @@
gdy constance nie jest jeszcze skonfigurowane (np. podczas migracji).
"""

_CONSTANCE_KEYS = (
"UZYWAJ_PUNKTACJI_WEWNETRZNEJ",
"POKAZUJ_INDEX_COPERNICUS",
"POKAZUJ_PUNKTACJA_SNIP",
"POKAZUJ_OSWIADCZENIE_KEN",
"SKROT_WYDZIALU_W_NAZWIE_JEDNOSTKI",
"UCZELNIA_UZYWA_WYDZIALOW",
"GOOGLE_ANALYTICS_PROPERTY_ID",
"GOOGLE_VERIFICATION_CODE",
"WYDRUK_MARGINES_GORA",
"WYDRUK_MARGINES_DOL",
"WYDRUK_MARGINES_LEWO",
"WYDRUK_MARGINES_PRAWO",
)


def constance_config(request):
"""
Udostępnia wybrane ustawienia z django-constance dla szablonów.

Używa ``constance.utils.get_values_for_keys`` zamiast
``getattr(config, key)``. Powód: od constance 4.x
``Config.__getattr__`` wykrywa aktywną pętlę asyncio (a Django
test client w nowszych wersjach startuje ją wewnętrznie) i
zwraca ``AsyncValueProxy`` — stringifikacja takiego proxy w
szablonie (``{{ VAR|default:"..." }}``) emituje
``RuntimeWarning: Synchronous access to Constance setting '...'
inside an async loop``. ``get_values_for_keys`` idzie prosto do
backendu, bez tej detekcji, więc działa identycznie w sync i
async kontekście.

Fallback: jeżeli constance nie jest skonfigurowane, używa wartości
z Django settings (ze zmiennych środowiskowych).

Returns:
dict: Słownik z ustawieniami dostępnymi w szablonach
"""
try:
from constance import config
from constance.utils import get_values_for_keys

return {
"UZYWAJ_PUNKTACJI_WEWNETRZNEJ": config.UZYWAJ_PUNKTACJI_WEWNETRZNEJ,
"POKAZUJ_INDEX_COPERNICUS": config.POKAZUJ_INDEX_COPERNICUS,
"POKAZUJ_PUNKTACJA_SNIP": config.POKAZUJ_PUNKTACJA_SNIP,
"POKAZUJ_OSWIADCZENIE_KEN": config.POKAZUJ_OSWIADCZENIE_KEN,
"SKROT_WYDZIALU_W_NAZWIE_JEDNOSTKI": (
config.SKROT_WYDZIALU_W_NAZWIE_JEDNOSTKI
),
"UCZELNIA_UZYWA_WYDZIALOW": config.UCZELNIA_UZYWA_WYDZIALOW,
"GOOGLE_ANALYTICS_PROPERTY_ID": config.GOOGLE_ANALYTICS_PROPERTY_ID,
"GOOGLE_VERIFICATION_CODE": config.GOOGLE_VERIFICATION_CODE,
"WYDRUK_MARGINES_GORA": config.WYDRUK_MARGINES_GORA,
"WYDRUK_MARGINES_DOL": config.WYDRUK_MARGINES_DOL,
"WYDRUK_MARGINES_LEWO": config.WYDRUK_MARGINES_LEWO,
"WYDRUK_MARGINES_PRAWO": config.WYDRUK_MARGINES_PRAWO,
}
return get_values_for_keys(_CONSTANCE_KEYS)
except (ImportError, AttributeError):
from django.conf import settings

Expand Down
13 changes: 13 additions & 0 deletions src/bpp/newsfragments/+constance-async-proxy.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Context processor ``bpp.context_processors.constance_config`` używa
teraz ``constance.utils.get_values_for_keys`` zamiast
``getattr(config, key)``. Od django-constance 4.x
``Config.__getattr__`` wykrywa aktywną pętlę ``asyncio`` i zwraca
``AsyncValueProxy`` zamiast bezpośredniej wartości. Django test
client w nowszych wersjach startuje pętlę wewnętrznie, więc w
testach (i faktycznie w ASGI-runtime) szablony renderujące
``{{ WYDRUK_MARGINES_GORA|default:"2cm" }}`` emitowały
``RuntimeWarning: Synchronous access to Constance setting
'WYDRUK_MARGINES_*' inside an async loop``.
``get_values_for_keys`` idzie prosto do backendu, bez detekcji
pętli, więc działa identycznie w obu kontekstach i nie odpala
warningu.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Zbumpowano ``django-denorm-iplweb`` z ``>=1.10.1`` do ``>=1.10.2``.
Release 1.10.2 dodaje ``get_joining_fields()`` do inline'owej
klasy ``JoinField`` w ``TriggerFilterQuery`` (``denorm/
denorms.py``), dzięki czemu Django 6.0 już nie emituje
``RemovedInDjango60Warning: The usage of get_joining_columns() in
Join is deprecated``.
17 changes: 17 additions & 0 deletions src/bpp/newsfragments/+moai-bump-and-pytest-filters.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Zbumpowano ``MOAI-iplweb`` z ``==2.0.0`` do ``>=2.0.1`` (release
2.0.1 zawiera fix ``datetime.utcnow()`` → ``datetime.now(UTC)``).
Zniknęły ostrzeżenia ``DeprecationWarning`` z ``moai/oai.py``.

Dodano dwa targetowane filtry w ``pytest.ini`` dla pozostałych
zewnętrznych warningów, których nie mamy gdzie naprawić w bpp:

- ``oaipmh.server`` (paczka ``pyoai`` 2.5.0) — wywołuje
``datetime.utcnow()``; nie mamy forka, zgłoszenie upstream
w toku.
- ``webtest.forms`` (paczka ``webtest`` 3.0.7) — używa
``bs4.findAll`` zamiast ``find_all``; nie mamy forka, zgłoszenie
do ``Pylons/webtest`` w toku.

Zmienione zależności tranzytywne (uv downgrade wymuszone przez
moai-iplweb ``sqlalchemy<2`` i ``setuptools<80``): ``sqlalchemy
2.0.44 → 1.4.54``, ``setuptools 80.9 → 79.0``.
18 changes: 18 additions & 0 deletions src/bpp/newsfragments/+naive-datetime-db-writes.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Naprawiono zapis naive datetime do pól ``DateTimeField`` w kilku
miejscach kodu produkcyjnego, które używały ``datetime.now()``
zamiast ``django.utils.timezone.now()``. Przy ``USE_TZ=True`` Django
wywoływało ``RuntimeWarning: received a naive datetime while time
zone support is active`` i interpretowało wartość w lokalnej strefie
czasowej — co przy zmianach DST mogło prowadzić do niespójności
dat w bazie.

Zasięg zmian:

- ``OptimizationRun.finished_at`` — zapisywane w
``ewaluacja_optymalizacja.tasks.optimization`` oraz w komendach
``solve_uczelnia`` i ``solve_evaluation``.
- ``remove_old_objects`` (``bpp.util``) — filtr wieku plików
używany m.in. przez ``remove_old_oswiadczenia_export_files``
i ``remove_old_integrator_files``.
- ``TemplateAdmin.template_updated`` — filtr rekordów do
przebudowy cache opisu bibliograficznego.
22 changes: 22 additions & 0 deletions src/bpp/newsfragments/+pagination-ordered-querysets.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Dodano stabilne ``order_by`` do QuerySetów, które były stronicowane
bez jawnego sortowania. Django emitowało wtedy
``UnorderedObjectListWarning: Pagination may yield inconsistent
results with an unordered object_list``, a kolejne strony mogły
zwracać zduplikowane lub pominięte rekordy.

Poprawione miejsca:

- Autocomplete w ``bpp.views.autocomplete``: ``Dyscyplina_Naukowa``
(``kod``), ``Wydawnictwo_Zwarte`` dla wydawnictwa nadrzędnego i
wariantów admina (``tytul_oryginalny``), ``Wydawnictwo_Ciagle``
admin (``tytul_oryginalny``), ``Zrodlo`` (``nazwa`` — zarówno
bazowy queryset jak i ``QuerySetSequence`` z priorytetami PBN).
- ``pbn_wysylka_oswiadczen.views.PublicationListView`` — combined
``QuerySetSequence`` sortowany ``-rok, tytul_oryginalny, pk``.
- ``RaportSlotowUczelnia.get_details_set()`` — sortowanie po
``autor__nazwisko, autor__imiona, pk`` dla stabilnej paginacji
szczegółów raportu.
- ``RozbieznosciView`` — dodano ``Meta.ordering = ["id"]`` (bazowy
abstrakcyjny model już miał tę opcję, ale lokalne ``Meta`` ją
nadpisywało). Migracja ``0021`` to wyłącznie ``AlterModelOptions``
(model jest ``managed = False``, brak DDL).
20 changes: 20 additions & 0 deletions src/bpp/newsfragments/+pbn-test-mocks-pageable.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Mocki danych testowych PBN dla endpointów paginowanych są teraz
owinięte w ``fixtures.pbn_api.pbn_pageable_json`` — zgodnie z
rzeczywistym kształtem odpowiedzi PBN (``{content, pageable,
number, totalElements, totalPages, ...}``). Wcześniej mocki zwracały
płaską listę / pustą listę, co w
``PBNClient._pages`` triggerowało
``RuntimeWarning: PBNClient.{get,post}_page request for ... did not
return a paged resource, maybe use PBNClient.{get,post} (without
'page') instead``. Produkcyjne wywołania
(``search_publications``, ``get_institution_publication_v2``,
``get_institution_statements_of_single_publication``) pozostają bez
zmian — to są paginowane endpointy PBN, więc ``get_pages`` /
``post_pages`` są poprawne; problem był tylko w mockach.

Poprawione pliki testowe:

- ``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``
19 changes: 19 additions & 0 deletions src/bpp/newsfragments/+pytest-assert-rewrite-fixtures.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Pytest nie emituje już ostrzeżeń ``PytestAssertRewriteWarning:
Module already imported so cannot be rewritten; fixtures.conftest_*``
(85 wystąpień w poprzednim runie). Przywrócono deklarację
``pytest_plugins = [...]`` w top-level ``src/conftest.py`` — pytest
rejestruje ``fixtures.conftest_{models,publications,system,browser,
disciplines}`` jako pluginy z aplikowanym assert-rewritingiem
przed ich pierwszym importem.

Jednocześnie ``fixtures/__init__.py`` przestał eager-importować
``conftest_*`` — wcześniejsze ``from .conftest_X import *``
pociągało te moduły przez łańcuch
``from fixtures.playwright_fixtures import ...`` → ``fixtures/
__init__.py`` PRZED rejestracją jako plugin, co właśnie generowało
ostrzeżenia.

Stałe (``NORMAL_DJANGO_USER_LOGIN/PASSWORD``, ``JEDNOSTKA_UCZELNI``,
``JEDNOSTKA_PODRZEDNA``) przeniesione do nowego modułu
``fixtures.const``, żeby ``from fixtures import X`` mogło je
re-eksportować bez ściągania modułów-pluginów.
6 changes: 6 additions & 0 deletions src/bpp/newsfragments/+pytest-mark-on-fixtures.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Usunięto redundantne dekoratory ``@pytest.mark.django_db`` nałożone
na fixtury w plikach ``conftest.py``. Pytest 8 ostrzegał
``PytestRemovedIn9Warning: Marks applied to fixtures have no
effect``, a sam marker i tak nie miał efektu — dostęp do bazy
danych w fixturach jest dziedziczony z testu wywołującego. W pytest 9
stosowanie markerów na fixturach będzie błędem.
16 changes: 16 additions & 0 deletions src/bpp/newsfragments/+tables-meta-model-mismatch.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Wyrównano ``class Meta: model = ...`` w tabelach ``django-tables2``
do faktycznego typu wierszy w QuerySecie. Dotychczas wyświetlane były
ostrzeżenia ``UserWarning: Table data is of type <X> but <Y> is
specified in Table.Meta.model``:

- ``RankingAutorowTable`` — ``model = Autor`` → ``model = Sumy``
(dane pochodzą z ``Nowe_Sumy_View`` / ``Sumy``, nie bezpośrednio
z ``Autor``).
- ``RaportSlotowUczelniaTable`` — ``model =
Cache_Punktacja_Autora_Query`` → ``model =
RaportSlotowUczelniaWiersz`` (widok listy iteruje po rekordach
``RaportSlotowUczelnia.raportslotowuczelniawiersz_set``).

``Meta.model`` w ``django-tables2`` służy tylko do introspekcji pól;
poza zniknięciem samego ostrzeżenia zachowanie tabel nie uległo
zmianie.
6 changes: 6 additions & 0 deletions src/bpp/newsfragments/+testreport-double-register.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Usunięto ``RuntimeWarning: Model 'long_running.testreport' was
already registered`` w testach ``long_running``. Testowy model
``TestReport`` został przeniesiony z inline'owej definicji we
fixturze do ``test_bpp.models`` wraz z migracją, dzięki czemu
model jest rejestrowany w ``apps`` tylko raz, a nie przy każdym
wywołaniu fixture'a.
19 changes: 19 additions & 0 deletions src/bpp/newsfragments/+wait-for-object-celery-retry.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
``long_running.util.wait_for_object`` nie blokuje już workera
``time.sleep``-em. W razie ``DoesNotExist`` woła
``current_task.retry(countdown=1, max_retries=no_tries)`` — celery
planuje ponowne uruchomienie tego samego zadania za sekundę, a worker
obsługuje w tym czasie inne zadania. Po wyczerpaniu prób celery
podnosi oryginalny ``DoesNotExist``. Zniknął też
``DeprecationWarning`` emitowany przy każdym wywołaniu.

Kontrakt: funkcję wywołujemy wyłącznie z kontekstu zadania celery
(``task.delay(...)``, ``.apply_async(...)``, ``.apply(...)``).
Wywołanie funkcji-zadania wprost jako zwykłej funkcji
(``task_func(pk)``) nie ustawia ``current_task`` i omija mechanizm
retry. Testy, które wcześniej wołały ``analyze_file`` i
``task_sprobuj_wyslac_do_pbn`` bezpośrednio, zostały przerobione
na wywołanie przez celery (``.delay(...).get()`` albo
``.apply(args=..., ...).get()`` — ``.apply()`` potrzebne tam, gdzie
test mockuje ``task.apply_async`` do weryfikacji re-schedulowania
i wtedy ``.delay()`` trafiłoby w mock zamiast uruchomić body
zadania).
2 changes: 1 addition & 1 deletion src/bpp/tests/test_cache/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ def cache_setup(db):

zwarte_dane = dict(
miejsce_i_rok="Lublin 2012",
wydawnictwo="Pholium",
wydawca_opis="Pholium",
redakcja="Redkacja",
isbn="isbn",
e_isbn="e_isbn",
Expand Down
5 changes: 0 additions & 5 deletions src/bpp/tests/test_models/test_sloty/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@


@pytest.fixture
@pytest.mark.django_db
def zwarte_z_dyscyplinami(
wydawnictwo_zwarte,
autor_jan_nowak,
Expand Down Expand Up @@ -56,7 +55,6 @@ def zwarte_z_dyscyplinami(


@pytest.fixture
@pytest.mark.django_db
def zwarte_z_dyscyplinami_hst(
wydawnictwo_zwarte,
autor_jan_nowak,
Expand Down Expand Up @@ -93,7 +91,6 @@ def zwarte_z_dyscyplinami_hst(


@pytest.fixture
@pytest.mark.django_db
def zwarte_z_dyscyplinami_hst_oraz_nie_hst(
wydawnictwo_zwarte,
autor_jan_nowak,
Expand Down Expand Up @@ -137,15 +134,13 @@ def zwarte_z_dyscyplinami_hst_oraz_nie_hst(


@pytest.fixture
@pytest.mark.django_db
def rodzaj_autora_n():
return Rodzaj_Autora.objects.get_or_create(
skrot="N", defaults={"licz_sloty": True, "sort": 1}
)[0]


@pytest.fixture
@pytest.mark.django_db
def ciagle_z_dyscyplinami(
wydawnictwo_ciagle,
autor_jan_nowak,
Expand Down
6 changes: 3 additions & 3 deletions src/bpp/tests/test_multiseek/test_multiseek_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
- StatusKorektyQueryObject - wyszukiwanie po statusie korekty
"""

from datetime import datetime

import pytest
from model_bakery import baker
from multiseek import logic
Expand All @@ -31,12 +29,14 @@
ZewnetrznaBazaDanychQueryObject,
)

from django.utils import timezone

pytestmark = pytest.mark.serial


@pytest.mark.django_db
def test_OstatnioZmieniony():
res = OstatnioZmieniony().real_query(datetime.now(), logic.EQUAL)
res = OstatnioZmieniony().real_query(timezone.now(), logic.EQUAL)
assert Rekord.objects.filter(res).count() == 0


Expand Down
Loading
Loading