diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index f5a2689de..e2203e621 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -43,7 +43,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ["3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@v6 diff --git a/.sonarcloud.properties b/.sonarcloud.properties index 3c641fd1e..4a692b685 100644 --- a/.sonarcloud.properties +++ b/.sonarcloud.properties @@ -10,7 +10,7 @@ sonar.sources=src # Encoding of the source code. Default is default system encoding #sonar.sourceEncoding=UTF-8 -sonar.python.version=3.10, 3.11, 3.12, 3.13 +sonar.python.version=3.10, 3.11, 3.12, 3.13, 3.14 sonar.tests=tests sonar.exclusions=src/argus/htmx/static/styles.css diff --git a/changelog.d/1725.added.md b/changelog.d/1725.added.md new file mode 100644 index 000000000..8f441bd5f --- /dev/null +++ b/changelog.d/1725.added.md @@ -0,0 +1,2 @@ +Added support for testing and running on Python 3.14, also leading to various +dependency upgrades centered around pydantic. diff --git a/pyproject.toml b/pyproject.toml index 74a8ea336..12643f7df 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: System :: Monitoring", ] dependencies = [ diff --git a/requirements-django52.txt b/requirements-django52.txt index 1052c7753..56dc9a710 100644 --- a/requirements-django52.txt +++ b/requirements-django52.txt @@ -1,5 +1,9 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --no-strip-extras --output-file requirements-django52.txt pyproject.toml requirements/django52.txt constraints.txt +# +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: +# +# pip-compile --no-strip-extras --output-file=requirements-django52.txt constraints.txt pyproject.toml requirements/django52.txt +# annotated-types==0.7.0 # via pydantic anyio==4.12.1 @@ -38,7 +42,7 @@ defusedxml==0.7.1 # social-auth-core dj-database-url==3.1.2 # via argus-server (pyproject.toml) -django==5.2.11 +django==5.2.13 # via # -r requirements/django52.txt # argus-server (pyproject.toml) @@ -131,9 +135,9 @@ psycopg-c==3.3.3 # via psycopg pycparser==3.0 # via cffi -pydantic==2.12.5 +pydantic==2.13.3 # via argus-server (pyproject.toml) -pydantic-core==2.41.5 +pydantic-core==2.46.3 # via pydantic pyjwt[crypto]==2.11.0 # via @@ -177,12 +181,13 @@ sqlparse==0.5.5 typing-extensions==4.15.0 # via # anyio - # dj-database-url # django-stubs-ext # django-tasks # django-tasks-db + # psycopg # pydantic # pydantic-core + # referencing # typing-inspection typing-inspection==0.4.2 # via pydantic diff --git a/requirements-django60.txt b/requirements-django60.txt index 867d9ffb7..5e4d74038 100644 --- a/requirements-django60.txt +++ b/requirements-django60.txt @@ -1,5 +1,9 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --no-strip-extras --output-file requirements-django60.txt pyproject.toml requirements/django60.txt constraints.txt +# +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: +# +# pip-compile --no-strip-extras --output-file=requirements-django60.txt constraints.txt pyproject.toml requirements/django60.txt +# annotated-types==0.7.0 # via pydantic anyio==4.12.1 @@ -38,7 +42,7 @@ defusedxml==0.7.1 # social-auth-core dj-database-url==3.1.2 # via argus-server (pyproject.toml) -django==6.0.2 +django==6.0.4 # via # -r requirements/django60.txt # argus-server (pyproject.toml) @@ -131,9 +135,9 @@ psycopg-c==3.3.3 # via psycopg pycparser==3.0 # via cffi -pydantic==2.12.5 +pydantic==2.13.3 # via argus-server (pyproject.toml) -pydantic-core==2.41.5 +pydantic-core==2.46.3 # via pydantic pyjwt[crypto]==2.11.0 # via @@ -176,11 +180,14 @@ sqlparse==0.5.5 # via django typing-extensions==4.15.0 # via + # anyio # django-stubs-ext # django-tasks # django-tasks-db + # psycopg # pydantic # pydantic-core + # referencing # typing-inspection typing-inspection==0.4.2 # via pydantic diff --git a/requirements.txt b/requirements.txt index 5bf6cd2d8..56dc9a710 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,39 +1,48 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --no-strip-extras --output-file requirements-django52.txt pyproject.toml requirements/django52.txt constraints.txt +# +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: +# +# pip-compile --no-strip-extras --output-file=requirements-django52.txt constraints.txt pyproject.toml requirements/django52.txt +# annotated-types==0.7.0 # via pydantic -anyio==4.9.0 +anyio==4.12.1 # via httpx -asgiref==3.8.1 +apprise==1.9.7 + # via argus-server (pyproject.toml) +asgiref==3.11.1 # via # django # django-cors-headers # django-htmx -attrs==25.3.0 +attrs==25.4.0 # via # -r constraints.txt # jsonschema # referencing -certifi==2025.4.26 +certifi==2026.2.25 # via + # apprise # httpcore # httpx # requests cffi==2.0.0 # via cryptography -charset-normalizer==3.4.2 +charset-normalizer==3.4.4 # via requests +click==8.3.1 + # via apprise cryptography==46.0.5 # via # -r constraints.txt - # social-auth-core + # pyjwt defusedxml==0.7.1 # via # python3-openid # social-auth-core -dj-database-url==2.3.0 +dj-database-url==3.1.2 # via argus-server (pyproject.toml) -django==5.2.9 +django==5.2.13 # via # -r requirements/django52.txt # argus-server (pyproject.toml) @@ -50,19 +59,19 @@ django==5.2.9 # djangorestframework # drf-spectacular # social-auth-app-django -django-cors-headers==4.7.0 +django-cors-headers==4.9.0 # via argus-server (pyproject.toml) -django-filter==25.1 +django-filter==25.2 # via argus-server (pyproject.toml) -django-htmx==1.23.0 +django-htmx==1.27.0 # via argus-server (pyproject.toml) -django-phonenumber-field[phonenumberslite]==8.1.0 +django-phonenumber-field[phonenumberslite]==8.4.0 # via argus-server (pyproject.toml) django-psycopg-infinity==0.1.0 # via argus-server (pyproject.toml) django-rest-knox==5.0.2 # via argus-server (pyproject.toml) -django-stubs-ext==5.2.7 +django-stubs-ext==5.2.9 # via # django-tasks # django-tasks-db @@ -72,7 +81,7 @@ django-tasks-db==0.12.0 # via argus-server (pyproject.toml) django-widget-tweaks==1.5.0 # via argus-server (pyproject.toml) -djangorestframework==3.16.0 +djangorestframework==3.16.1 # via # argus-server (pyproject.toml) # django-rest-knox @@ -80,11 +89,11 @@ djangorestframework==3.16.0 # drf-spectacular drf-rw-serializers==1.4.0 # via argus-server (pyproject.toml) -drf-spectacular==0.28.0 +drf-spectacular==0.29.0 # via argus-server (pyproject.toml) factory-boy==3.3.3 # via argus-server (pyproject.toml) -faker==37.3.0 +faker==40.5.1 # via factory-boy fontawesomefree==6.6.0 # via argus-server (pyproject.toml) @@ -94,26 +103,28 @@ httpcore==1.0.9 # via httpx httpx==0.28.1 # via argus-server (pyproject.toml) -idna==3.10 +idna==3.11 # via # anyio # httpx # requests inflection==0.5.1 # via drf-spectacular -jsonschema==4.23.0 +jsonschema==4.26.0 # via drf-spectacular -jsonschema-specifications==2025.4.1 +jsonschema-specifications==2025.9.1 # via jsonschema -oauthlib==3.2.2 +markdown==3.10.2 + # via apprise +oauthlib==3.3.1 # via # requests-oauthlib # social-auth-core -packaging==25.0 +packaging==26.0 # via # -r constraints.txt # wheel -phonenumberslite==9.0.5 +phonenumberslite==9.0.25 # via django-phonenumber-field psycopg[c]==3.3.3 # via @@ -122,61 +133,65 @@ psycopg[c]==3.3.3 # django-psycopg-infinity psycopg-c==3.3.3 # via psycopg -pycparser==2.22 +pycparser==3.0 # via cffi -pydantic==2.11.5 +pydantic==2.13.3 # via argus-server (pyproject.toml) -pydantic-core==2.33.2 +pydantic-core==2.46.3 # via pydantic -pyjwt==2.10.1 - # via social-auth-core +pyjwt[crypto]==2.11.0 + # via + # pyjwt + # social-auth-core python-dataporten-auth==2.0.0 # via argus-server (pyproject.toml) python3-openid==3.2.0 # via social-auth-core -pyyaml==6.0.2 +pyyaml==6.0.3 # via # -r constraints.txt + # apprise # drf-spectacular -referencing==0.36.2 +referencing==0.37.0 # via # jsonschema # jsonschema-specifications -requests==2.32.4 +requests==2.32.5 # via + # apprise # requests-oauthlib # social-auth-core requests-oauthlib==2.0.0 - # via social-auth-core -rpds-py==0.25.1 + # via + # apprise + # social-auth-core +rpds-py==0.30.0 # via # jsonschema # referencing -sniffio==1.3.1 - # via anyio -social-auth-app-django==5.6.0 +social-auth-app-django==5.7.0 # via argus-server (pyproject.toml) -social-auth-core==4.6.1 +social-auth-core==4.8.5 # via # argus-server (pyproject.toml) # python-dataporten-auth # social-auth-app-django sqlparse==0.5.5 # via django -typing-extensions==4.13.2 +typing-extensions==4.15.0 # via - # dj-database-url + # anyio # django-stubs-ext # django-tasks # django-tasks-db + # psycopg # pydantic # pydantic-core + # referencing # typing-inspection -typing-inspection==0.4.1 +typing-inspection==0.4.2 # via pydantic -tzdata==2025.2 - # via faker -uritemplate==4.1.1 +uritemplate==4.2.0 # via drf-spectacular urllib3==2.6.3 # via @@ -184,5 +199,5 @@ urllib3==2.6.3 # requests wheel==0.46.3 # via argus-server (pyproject.toml) -whitenoise==6.9.0 +whitenoise==6.12.0 # via argus-server (pyproject.toml) diff --git a/src/argus/dev/utils.py b/src/argus/dev/utils.py index 64440d0f1..9aeb9b486 100644 --- a/src/argus/dev/utils.py +++ b/src/argus/dev/utils.py @@ -33,7 +33,10 @@ def __init__(self, url: str, token: str, timeout: int, worker_count: int): self.token = token self.timeout = timeout self.worker_count = worker_count - self._loop = asyncio.get_event_loop() + try: + self._loop = asyncio.get_running_loop() + except RuntimeError: + self._loop = asyncio.new_event_loop() def _get_incident_data(self) -> dict[str, Any]: return { diff --git a/tox.ini b/tox.ini index 26564ce0c..829700735 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ envlist = clean py{310,311}-django{52} - py{312,313}-django{52,60} + py{312,313,314}-django{52,60} coverage-html skipsdist = True skip_missing_interpreters = True @@ -14,6 +14,7 @@ python = 3.11: py311 3.12: py312 3.13: py313 + 3.14: py314 [testenv:clean] deps =