From 1e4ffa5b924049aa155d0b86fa532a69d9937baa Mon Sep 17 00:00:00 2001 From: Alex Kanitz Date: Mon, 20 May 2024 03:25:01 +0200 Subject: [PATCH 1/4] build: drop py3.8 support --- .github/workflows/checks.yml | 2 -- examples/petstore-access-control/README.md | 2 +- examples/petstore/README.md | 2 +- setup.py | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index f66093e1..31ffaaba 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -19,7 +19,6 @@ jobs: fail-fast: true matrix: py-version-img: [ - ["3.8", "3.8-slim-bullseye"], ["3.9", "3.9-slim-bullseye"], ["3.10", "3.10-slim-bullseye"], ["3.11", "3.11-slim-bullseye"] @@ -83,7 +82,6 @@ jobs: fail-fast: true matrix: py-version-img-tag: [ - ["3.8", "3.8-slim-bullseye", ""], ["3.9", "3.9-slim-bullseye", ""], ["3.10", "3.10-slim-bullseye", ""], ["3.11", "3.11-slim-bullseye", "latest"], diff --git a/examples/petstore-access-control/README.md b/examples/petstore-access-control/README.md index c6595a64..5c274b51 100644 --- a/examples/petstore-access-control/README.md +++ b/examples/petstore-access-control/README.md @@ -79,7 +79,7 @@ Some notes: > executing the build command. For example: > > ```bash -> export PETSTORE_PY_IMAGE=3.8-slim-buster +> export PETSTORE_PY_IMAGE=3.11-slim-bookworm > ``` > > * In case Docker complains about port conflicts or if any of the used ports diff --git a/examples/petstore/README.md b/examples/petstore/README.md index 04e2c4db..29791702 100644 --- a/examples/petstore/README.md +++ b/examples/petstore/README.md @@ -77,7 +77,7 @@ Some notes: > executing the build command. For example: > > ```bash -> export PETSTORE_PY_IMAGE=3.8-slim-buster +> export PETSTORE_PY_IMAGE=3.11-slim-bookworm > ``` > > * In case Docker complains about port conflicts or if any of the used ports diff --git a/setup.py b/setup.py index 641e6a49..5a5332a3 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,6 @@ "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", From a2c6c86c327b403b3ab5a2bf6eed267bf70f2a9f Mon Sep 17 00:00:00 2001 From: Alex Kanitz Date: Mon, 20 May 2024 03:32:31 +0200 Subject: [PATCH 2/4] ci: upgrade MongoDB --- .github/workflows/checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 31ffaaba..903c35d3 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -23,7 +23,7 @@ jobs: ["3.10", "3.10-slim-bullseye"], ["3.11", "3.11-slim-bullseye"] ] - mongodb-version: ["4.2", "4.4", "5.0"] + mongodb-version: ["4.4", "5.0", "6.0", "7.0"] mongodb-port: [12345] steps: From c0c68115a06f19d8131fdf4b8b876ad538dc3fa0 Mon Sep 17 00:00:00 2001 From: Alex Kanitz Date: Mon, 20 May 2024 05:06:57 +0200 Subject: [PATCH 3/4] build: relax dependency version constraints (#228) --- .github/workflows/checks.yml | 3 +- foca/models/config.py | 14 ++++---- .../foca_casbin_adapter/adapter.py | 4 ++- .../access_control/register_access_control.py | 20 ++++++----- foca/security/auth.py | 6 ++-- requirements.txt | 34 +++++++++---------- requirements_dev.txt | 24 ++++++------- requirements_docs.txt | 6 ++-- setup.py | 6 ++-- tests/api/controllers/__init__.py | 4 +-- .../test_access_control_server.py | 5 +-- 11 files changed, 67 insertions(+), 59 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 903c35d3..656a4bd6 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -34,8 +34,7 @@ jobs: python-version: ${{ matrix.py-version-img[0] }} - name: Install requirements run: | - pip install -e . - pip install -r requirements_dev.txt + pip install -e .[dev] - name: Lint with flake8 run: flake8 - name: Run mypy diff --git a/foca/models/config.py b/foca/models/config.py index 5bbe8c64..f36bd95e 100644 --- a/foca/models/config.py +++ b/foca/models/config.py @@ -19,7 +19,7 @@ ) -def _validate_log_level_choices(level: int) -> int: +def _validate_log_level_choices(cls, level: int) -> int: """Custom validation function for Pydantic to ensure that a valid logging level is configured. @@ -32,9 +32,9 @@ def _validate_log_level_choices(level: int) -> int: Raises: ValueError: Raised if validation fails. """ - choices = [0, 10, 20, 30, 40, 50] - if level not in choices: - raise ValueError("illegal log level specified") + CHOICES = [0, 10, 20, 30, 40, 50] + if level not in CHOICES: + raise ValueError(f"illegal log level specified: {level}") return level @@ -593,7 +593,7 @@ def set_abs_path(cls, v): # pylint: disable=E0213 absolute path provided. """ # if path is not a list, convert it to single-item list - if(isinstance(v, Path)): + if (isinstance(v, Path)): if not v.is_absolute(): return [Path.cwd() / v] return [v] @@ -1181,10 +1181,10 @@ class LogConfig(FOCABaseConfig): version: int = 1 disable_existing_loggers: bool = False formatters: Optional[Dict[str, LogFormatterConfig]] = { - "standard": LogFormatterConfig(), + "standard": LogFormatterConfig(), # type: ignore } handlers: Optional[Dict[str, LogHandlerConfig]] = { - "console": LogHandlerConfig(), + "console": LogHandlerConfig(), # type: ignore } root: Optional[LogRootConfig] = LogRootConfig() diff --git a/foca/security/access_control/foca_casbin_adapter/adapter.py b/foca/security/access_control/foca_casbin_adapter/adapter.py index 26f1fe45..a6f0a0c7 100644 --- a/foca/security/access_control/foca_casbin_adapter/adapter.py +++ b/foca/security/access_control/foca_casbin_adapter/adapter.py @@ -42,7 +42,9 @@ def __init__( self._collection = db[collection] def load_policy(self, model: CasbinRule): - """Implementing add Interface for casbin. Load all policy rules from mongodb + """Implementing add Interface for casbin. + + Load all policy rules from MongoDB. Args: model: CasbinRule object. diff --git a/foca/security/access_control/register_access_control.py b/foca/security/access_control/register_access_control.py index a7bc10d7..8bea8c9a 100644 --- a/foca/security/access_control/register_access_control.py +++ b/foca/security/access_control/register_access_control.py @@ -1,14 +1,16 @@ """Methods to manage permission management configuration""" import logging -from connexion import App -from connexion.exceptions import Forbidden -from flask_authz import CasbinEnforcer +from functools import wraps from pkg_resources import resource_filename +from pathlib import Path from typing import (Callable, Optional, Tuple) -from functools import wraps + +from connexion import App +from connexion.exceptions import Forbidden from flask import current_app from flask.wrappers import Response +from flask_authz import CasbinEnforcer from foca.models.config import ( DBConfig, @@ -50,7 +52,7 @@ def register_access_control( access_db_conf = DBConfig( collections={ access_control_config.collection_name: CollectionConfig() - }, + } if access_control_config.collection_name is not None else {}, client=None ) @@ -113,7 +115,7 @@ def register_permission_specs( spec_path = access_control_config.api_specs spec = SpecConfig( - path=spec_path, + path=Path(spec_path), add_operation_fields={ "x-openapi-router-controller": ( access_control_config.api_controllers @@ -191,7 +193,9 @@ def check_permissions( """ def _decorator_check_permissions(fn): - """User access decorator. Used to facilitate optional decorator arguments. + """User access decorator. + + Used to facilitate optional decorator arguments. Args: fn: The function to be decorated. @@ -200,7 +204,7 @@ def _decorator_check_permissions(fn): The response returned from the input function. """ @wraps(fn) - def _wrapper(*args, **kwargs): + def _wrapper(*args, **kwargs) -> Tuple[Response, int]: """Wrapper for permissions decorator. Args: diff --git a/foca/security/auth.py b/foca/security/auth.py index 5d389e41..d0f3468c 100644 --- a/foca/security/auth.py +++ b/foca/security/auth.py @@ -319,7 +319,9 @@ def _get_public_keys( public_keys = {} for jwk in response.json().get(claim_keys, []): try: - key = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(jwk)) + key = jwt.algorithms.RSAAlgorithm.from_jwk( # type:ignore + json.dumps(jwk) + ) # Ensure key is public if not isinstance(key, RSAPublicKey): @@ -328,7 +330,7 @@ def _get_public_keys( # Convert to PEM if requested if pem: - key = key.public_bytes( + key = key.public_bytes( # type: ignore encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo, ).decode('utf-8').encode('unicode_escape').decode('utf-8') diff --git a/requirements.txt b/requirements.txt index 2a549a25..a1c369c3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,17 +1,17 @@ -addict==2.2.1 -celery==5.2.2 -connexion>=2.11.2,<3.0.0 -cryptography==42.0.4 -Flask==2.2.5 -flask-authz==2.5.1 -Flask-Cors==4.0.1 -Flask-PyMongo==2.3.0 -pydantic==1.10.13 -PyJWT==2.4.0 -pymongo==4.7.2 -PyYAML==6.0.1 -requests==2.31.0 -swagger-ui-bundle==0.0.6 -toml==0.10.0 -typing==3.7.4.1 -Werkzeug>=2.2.2,<3.0.0 +addict~=2.2 +celery~=5.2 +connexion~=2.11 +cryptography~=42.0 +Flask~=2.2 +flask-authz~=2.5 +Flask-Cors~=4.0 +Flask-PyMongo~=2.3 +pydantic~=1.10 +PyJWT~=2.4 +pymongo~=4.7 +PyYAML~=6.0 +requests~=2.31 +swagger-ui-bundle~=0.0 +toml~=0.10 +typing~=3.7 +Werkzeug~=2.2 diff --git a/requirements_dev.txt b/requirements_dev.txt index 07b4ec1f..b7c26554 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,12 +1,12 @@ -coverage==6.3.2 -flake8==4.0.1 -mongomock==4.0.0 -mypy==0.971 -mypy-extensions==0.4.3 -pylint==2.13.2 -pytest==7.1.1 -python-semantic-release==7.32.2 -types-PyYAML==6.0.12 -types-requests==2.28.11 -types-setuptools==65.3.0 -types-urllib3==1.26.25 +coverage>=6.5 +flake8>=6.1 +mongomock>=4.1 +mypy>=0.991 +mypy-extensions>=0.4.4 +pylint>=3.2 +pytest>=7.4 +python-semantic-release>=7.34,<8.2 +types-PyYAML +types-requests +types-setuptools +types-urllib3 diff --git a/requirements_docs.txt b/requirements_docs.txt index 5b644e38..032b5e77 100644 --- a/requirements_docs.txt +++ b/requirements_docs.txt @@ -1,3 +1,3 @@ -Sphinx==7.2.6 -readthedocs-sphinx-ext==2.2.3 -sphinx-rtd-theme==1.3.0 \ No newline at end of file +Sphinx>=7.2 +readthedocs-sphinx-ext>=2.2 +sphinx-rtd-theme>=1.3 diff --git a/setup.py b/setup.py index 5a5332a3..d6f53f79 100644 --- a/setup.py +++ b/setup.py @@ -73,13 +73,13 @@ }, packages=find_packages(), setup_requires=[ - "setuptools_git==1.2", - "twine==3.8.0" + "setuptools_git>=1.2", + "twine>=3.8.0" ], install_requires=install_requires, extras_require={ - "docs": docs_require, "dev": dev_requires, + "docs": docs_require, }, include_package_data=True, package_data={ diff --git a/tests/api/controllers/__init__.py b/tests/api/controllers/__init__.py index 3aa6b9cc..47cc04b9 100644 --- a/tests/api/controllers/__init__.py +++ b/tests/api/controllers/__init__.py @@ -6,11 +6,11 @@ def listPets(): def createPets(): - return{} + return {} def showPetById(): - return{} + return {} def putPetsById(): diff --git a/tests/security/access_control/test_access_control_server.py b/tests/security/access_control/test_access_control_server.py index 56d24e8d..bdd357b1 100644 --- a/tests/security/access_control/test_access_control_server.py +++ b/tests/security/access_control/test_access_control_server.py @@ -193,8 +193,9 @@ def test_getAllPermissions(self): assert res == [data] def test_getAllPermissions_filters(self): - """Test for getting a list of all available permissions; all defined filters - specified. + """Test for getting a list of all available permissions. + + All defined filters specified. """ app = Flask(__name__) base_config = Config(db=MongoConfig(**MONGO_CONFIG)) From 7898affe2c1f79308d2cc0b8d874bcf92dd1f2f0 Mon Sep 17 00:00:00 2001 From: Alex Kanitz Date: Mon, 20 May 2024 05:21:17 +0200 Subject: [PATCH 4/4] build: use Debian 12 in Python base images --- .github/workflows/checks.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 656a4bd6..28995a32 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -19,9 +19,9 @@ jobs: fail-fast: true matrix: py-version-img: [ - ["3.9", "3.9-slim-bullseye"], - ["3.10", "3.10-slim-bullseye"], - ["3.11", "3.11-slim-bullseye"] + ["3.9", "3.9-slim-bookworm"], + ["3.10", "3.10-slim-bookworm"], + ["3.11", "3.11-slim-bookworm"] ] mongodb-version: ["4.4", "5.0", "6.0", "7.0"] mongodb-port: [12345] @@ -81,9 +81,9 @@ jobs: fail-fast: true matrix: py-version-img-tag: [ - ["3.9", "3.9-slim-bullseye", ""], - ["3.10", "3.10-slim-bullseye", ""], - ["3.11", "3.11-slim-bullseye", "latest"], + ["3.9", "3.9-slim-bookworm", ""], + ["3.10", "3.10-slim-bookworm", ""], + ["3.11", "3.11-slim-bookworm", "latest"], ] steps: