From 2d47fb5f3c72795f6865c15959d1a87b8ded8517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Fri, 10 Jul 2026 17:46:41 -0300 Subject: [PATCH 01/10] Convert package to a native namespace Closes #105 --- news/105.internal | 1 + src/pas/__init__.py | 1 - src/pas/plugins/__init__.py | 1 - tests/__init__.py | 0 tests/functional/__init__.py | 0 tests/plugin/__init__.py | 0 tests/services/__init__.py | 0 tests/setup/__init__.py | 0 8 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 news/105.internal delete mode 100644 src/pas/__init__.py delete mode 100644 src/pas/plugins/__init__.py create mode 100644 tests/__init__.py create mode 100644 tests/functional/__init__.py create mode 100644 tests/plugin/__init__.py create mode 100644 tests/services/__init__.py create mode 100644 tests/setup/__init__.py diff --git a/news/105.internal b/news/105.internal new file mode 100644 index 0000000..c95c867 --- /dev/null +++ b/news/105.internal @@ -0,0 +1 @@ +Converted the package to a PEP 420 native namespace, dropping the legacy `pkg_resources` namespace declarations. @ericof diff --git a/src/pas/__init__.py b/src/pas/__init__.py deleted file mode 100644 index 5284146..0000000 --- a/src/pas/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__import__("pkg_resources").declare_namespace(__name__) diff --git a/src/pas/plugins/__init__.py b/src/pas/plugins/__init__.py deleted file mode 100644 index 5284146..0000000 --- a/src/pas/plugins/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__import__("pkg_resources").declare_namespace(__name__) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/functional/__init__.py b/tests/functional/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/plugin/__init__.py b/tests/plugin/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/services/__init__.py b/tests/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/setup/__init__.py b/tests/setup/__init__.py new file mode 100644 index 0000000..e69de29 From fa83f521a16615f1cc196efc366a2282a183d761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Fri, 10 Jul 2026 17:46:46 -0300 Subject: [PATCH 02/10] Support Plone 6.2 and Python 3.14; drop Plone 6.0 and Python 3.10 Closes #106 Closes #107 Closes #108 Closes #109 --- .github/workflows/changelog.yml | 2 +- .github/workflows/config.yml | 4 ++-- .github/workflows/main.yml | 4 ++-- news/106.feature | 1 + news/107.breaking | 1 + news/108.feature | 1 + news/109.breaking | 1 + pyproject.toml | 19 +++++++++---------- 8 files changed, 18 insertions(+), 15 deletions(-) create mode 100644 news/106.feature create mode 100644 news/107.breaking create mode 100644 news/108.feature create mode 100644 news/109.breaking diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index fd1bbce..3acacb8 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -6,7 +6,7 @@ on: - main env: - python-version: 3.12 + python-version: 3.14 jobs: build: diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml index 8cc08e9..ad88c31 100644 --- a/.github/workflows/config.yml +++ b/.github/workflows/config.yml @@ -6,11 +6,11 @@ on: python-version: required: false type: string - default: "3.12" + default: "3.14" plone-version: required: false type: string - default: "6.1.1" + default: "6.2.1" outputs: backend: description: "Flag reporting if we should run the backend jobs" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3961092..e639a66 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,8 +23,8 @@ jobs: - config strategy: matrix: - python-version: ["3.13", "3.12", "3.11", "3.10"] - plone-version: ["6.1-latest", "6.0-latest"] + python-version: ["3.14", "3.13", "3.12", "3.11"] + plone-version: ["6.2-latest", "6.1-latest"] with: python-version: ${{ matrix.python-version }} plone-version: ${{ matrix.plone-version }} diff --git a/news/106.feature b/news/106.feature new file mode 100644 index 0000000..e226236 --- /dev/null +++ b/news/106.feature @@ -0,0 +1 @@ +Added support for Plone 6.2. @ericof diff --git a/news/107.breaking b/news/107.breaking new file mode 100644 index 0000000..61d8689 --- /dev/null +++ b/news/107.breaking @@ -0,0 +1 @@ +Dropped support for Plone 6.0. @ericof diff --git a/news/108.feature b/news/108.feature new file mode 100644 index 0000000..56af7c4 --- /dev/null +++ b/news/108.feature @@ -0,0 +1 @@ +Added support for Python 3.14. @ericof diff --git a/news/109.breaking b/news/109.breaking new file mode 100644 index 0000000..67cf77f --- /dev/null +++ b/news/109.breaking @@ -0,0 +1 @@ +Dropped support for Python 3.10. @ericof diff --git a/pyproject.toml b/pyproject.toml index 10450f6..e3cf357 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ dynamic = ["version"] description = "Provides OAuth2/OpenID login for Plone using Authomatic." readme = "README.md" license = {text = "GNU General Public License v2 (GPLv2)"} -requires-python = ">=3.10" +requires-python = ">=3.11" authors = [ { name = "Jens Klein", email = "dev@bluedynamics.com" }, { name = "Érico Andrei", email = "ericof@plone.org" }, @@ -21,23 +21,22 @@ classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Plone", - "Framework :: Plone :: 6.0", "Framework :: Plone :: 6.1", + "Framework :: Plone :: 6.2", "Framework :: Plone :: Addon", "Framework :: Zope", "Framework :: Zope :: 5", - "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ] dependencies = [ - "Products.CMFPlone>=6.0", + "Products.CMFPlone>=6.1", "authomatic>=1.3.0", - "plone.restapi>=9.10.0", + "plone.restapi", "plone.api", ] @@ -49,9 +48,9 @@ test = [ "plone.restapi[test]", "zest.releaser[recommended]", "pytest-cov", - "pytest-plone>=1.0.0a1", - "zest-releaser[recommended]>=9.5.0", - "zestreleaser-towncrier>=1.3.0", + "pytest-plone>=1.0.0", + "zest-releaser[recommended]", + "zestreleaser-towncrier", ] [project.urls] @@ -140,7 +139,7 @@ enable-unstable-feature = [ ] [tool.ruff] -target-version = "py310" +target-version = "py311" line-length = 88 fix = true lint.select = [ From 07e57fe6edb338137e05e7abaa72dee55c893e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Fri, 10 Jul 2026 17:46:52 -0300 Subject: [PATCH 03/10] Consolidate package logger and modernize imports Move the logger to pas.plugins.authomatic.logger, drop log.py, and update the INavigationRoot import to plone.base. --- news/+logging.internal | 1 + src/pas/plugins/authomatic/__init__.py | 6 +++++- src/pas/plugins/authomatic/browser/view.py | 8 ++------ src/pas/plugins/authomatic/integration/restapi.py | 7 ++----- src/pas/plugins/authomatic/integration/zope.py | 7 ++----- src/pas/plugins/authomatic/log.py | 6 ------ src/pas/plugins/authomatic/patches/__init__.py | 7 +++++-- src/pas/plugins/authomatic/patches/authomatic.py | 4 ++-- src/pas/plugins/authomatic/plugin.py | 6 ++---- src/pas/plugins/authomatic/services/authomatic.py | 5 +---- src/pas/plugins/authomatic/useridentities.py | 11 ++++------- 11 files changed, 26 insertions(+), 42 deletions(-) create mode 100644 news/+logging.internal delete mode 100644 src/pas/plugins/authomatic/log.py diff --git a/news/+logging.internal b/news/+logging.internal new file mode 100644 index 0000000..c535081 --- /dev/null +++ b/news/+logging.internal @@ -0,0 +1 @@ +Consolidated the package logger into a single `pas.plugins.authomatic.logger` and removed the redundant `log.py` module. @ericof diff --git a/src/pas/plugins/authomatic/__init__.py b/src/pas/plugins/authomatic/__init__.py index be227e3..2962bf3 100644 --- a/src/pas/plugins/authomatic/__init__.py +++ b/src/pas/plugins/authomatic/__init__.py @@ -1,5 +1,7 @@ from pas.plugins.authomatic.patches import apply_patches +import logging + __version__ = "2.0.1.dev0" @@ -7,7 +9,9 @@ PACKAGE_NAME = "pas.plugins.authomatic" -apply_patches() +logger = logging.getLogger(PACKAGE_NAME) + +apply_patches(logger) def initialize(context): diff --git a/src/pas/plugins/authomatic/browser/view.py b/src/pas/plugins/authomatic/browser/view.py index 4ad9193..9ae5e66 100644 --- a/src/pas/plugins/authomatic/browser/view.py +++ b/src/pas/plugins/authomatic/browser/view.py @@ -1,10 +1,11 @@ from authomatic import Authomatic +from pas.plugins.authomatic import logger from pas.plugins.authomatic.integration import ZopeRequestAdapter from pas.plugins.authomatic.interfaces import _ from pas.plugins.authomatic.utils import authomatic_cfg from pas.plugins.authomatic.utils import authomatic_settings from plone import api -from plone.app.layout.navigation.interfaces import INavigationRoot +from plone.base.interfaces.siteroot import INavigationRoot from plone.protect.interfaces import IDisableCSRFProtection from Products.CMFCore.interfaces import ISiteRoot from Products.Five.browser import BrowserView @@ -13,11 +14,6 @@ from zope.interface import implementer from zope.publisher.interfaces import IPublishTraverse -import logging - - -logger = logging.getLogger(__file__) - def is_root(obj): """Check if current context is Navigation root or a Portal.""" diff --git a/src/pas/plugins/authomatic/integration/restapi.py b/src/pas/plugins/authomatic/integration/restapi.py index a1737c5..293c92b 100644 --- a/src/pas/plugins/authomatic/integration/restapi.py +++ b/src/pas/plugins/authomatic/integration/restapi.py @@ -1,9 +1,5 @@ from authomatic.adapters import BaseAdapter - -import logging - - -logger = logging.getLogger(__file__) +from pas.plugins.authomatic import logger Headers = dict | None @@ -12,6 +8,7 @@ class RestAPIAdapter(BaseAdapter): """Adapter for plone.restapi usage.""" + headers: dict[str, str] frontend_route: str = "login-authomatic" def __init__( diff --git a/src/pas/plugins/authomatic/integration/zope.py b/src/pas/plugins/authomatic/integration/zope.py index 628c925..d638137 100644 --- a/src/pas/plugins/authomatic/integration/zope.py +++ b/src/pas/plugins/authomatic/integration/zope.py @@ -1,10 +1,7 @@ from authomatic.adapters import BaseAdapter +from pas.plugins.authomatic import logger import http -import logging - - -logger = logging.getLogger(__file__) class ZopeRequestAdapter(BaseAdapter): @@ -53,7 +50,7 @@ def set_header(self, key, value): self.view.request.response.setHeader(key, value) def set_status(self, status): - code, message = status.split(" ") + code, _ = status.split(" ") code = int(code) logger.debug(f"set_status {code}") self.view.request.response.setStatus(code) diff --git a/src/pas/plugins/authomatic/log.py b/src/pas/plugins/authomatic/log.py deleted file mode 100644 index 3d5abc5..0000000 --- a/src/pas/plugins/authomatic/log.py +++ /dev/null @@ -1,6 +0,0 @@ -from pas.plugins.authomatic import PACKAGE_NAME - -import logging - - -logger = logging.getLogger(PACKAGE_NAME) diff --git a/src/pas/plugins/authomatic/patches/__init__.py b/src/pas/plugins/authomatic/patches/__init__.py index b364836..3d1c6f4 100644 --- a/src/pas/plugins/authomatic/patches/__init__.py +++ b/src/pas/plugins/authomatic/patches/__init__.py @@ -1,5 +1,8 @@ -def apply_patches(): +from logging import Logger + + +def apply_patches(logger: Logger): """Apply patches.""" from .authomatic import patch_base_provider_fetch - patch_base_provider_fetch() + patch_base_provider_fetch(logger) diff --git a/src/pas/plugins/authomatic/patches/authomatic.py b/src/pas/plugins/authomatic/patches/authomatic.py index ac18aa7..f9c469b 100644 --- a/src/pas/plugins/authomatic/patches/authomatic.py +++ b/src/pas/plugins/authomatic/patches/authomatic.py @@ -1,14 +1,14 @@ from authomatic.exceptions import FetchError from authomatic.providers import BaseProvider from http import client as http_client -from pas.plugins.authomatic.log import logger +from logging import Logger from urllib import parse import authomatic.core import ssl -def patch_base_provider_fetch(): +def patch_base_provider_fetch(logger: Logger): def _fetch( self, url, diff --git a/src/pas/plugins/authomatic/plugin.py b/src/pas/plugins/authomatic/plugin.py index 6aa5f16..571e011 100644 --- a/src/pas/plugins/authomatic/plugin.py +++ b/src/pas/plugins/authomatic/plugin.py @@ -2,6 +2,7 @@ from AccessControl.class_init import InitializeClass from BTrees.OOBTree import OOBTree from operator import itemgetter +from pas.plugins.authomatic import logger from pas.plugins.authomatic.interfaces import IAuthomaticPlugin from pas.plugins.authomatic.useridentities import UserIdentities from pas.plugins.authomatic.useridfactories import new_userid @@ -18,13 +19,10 @@ from zope.event import notify from zope.interface import implementer -import logging - -logger = logging.getLogger(__name__) tpl_dir = Path(__file__).parent.resolve() / "browser" -_marker = {} +_marker: dict[str, str] = {} def manage_addAuthomaticPlugin( diff --git a/src/pas/plugins/authomatic/services/authomatic.py b/src/pas/plugins/authomatic/services/authomatic.py index 19a2acf..d5cc643 100644 --- a/src/pas/plugins/authomatic/services/authomatic.py +++ b/src/pas/plugins/authomatic/services/authomatic.py @@ -1,4 +1,5 @@ from authomatic import Authomatic +from pas.plugins.authomatic import logger from pas.plugins.authomatic.integration import RestAPIAdapter from pas.plugins.authomatic.utils import authomatic_cfg from pas.plugins.authomatic.utils import authomatic_settings @@ -13,13 +14,9 @@ from zope.interface import implementer from zope.publisher.interfaces import IPublishTraverse -import logging import transaction -logger = logging.getLogger("pas.plugins.authomatic") - - @implementer(IPublishTraverse) class LoginAuthomatic(Service): """Base class for Authomatic login.""" diff --git a/src/pas/plugins/authomatic/useridentities.py b/src/pas/plugins/authomatic/useridentities.py index c1bd1bf..7eb9ca4 100644 --- a/src/pas/plugins/authomatic/useridentities.py +++ b/src/pas/plugins/authomatic/useridentities.py @@ -1,17 +1,14 @@ from authomatic.core import Credentials +from pas.plugins.authomatic import logger from pas.plugins.authomatic.utils import authomatic_cfg from persistent import Persistent -from persistent.dict import PersistentDict +from persistent.mapping import PersistentMapping from Products.PluggableAuthService.UserPropertySheet import UserPropertySheet -import logging import uuid -logger = logging.getLogger("pas.plugins.authomatic") - - -class UserIdentity(PersistentDict): +class UserIdentity(PersistentMapping): def __init__(self, result): super().__init__() self["provider_name"] = result.provider.name @@ -30,7 +27,7 @@ def credentials(self, credentials): class UserIdentities(Persistent): def __init__(self, userid): self.userid = userid - self._identities = PersistentDict() + self._identities = PersistentMapping() self._sheet = None self._secret = str(uuid.uuid4()) From 1d75e06317522f2b27b8334211bc9dc18236dfee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Fri, 10 Jul 2026 17:46:56 -0300 Subject: [PATCH 04/10] Reuse pytest-plone 1.0.0 fixtures in service tests --- news/+pytest-plone.tests | 1 + tests/services/conftest.py | 24 ++-------------------- tests/services/test_services_authomatic.py | 4 ++-- tests/services/test_services_login.py | 4 ++-- 4 files changed, 7 insertions(+), 26 deletions(-) create mode 100644 news/+pytest-plone.tests diff --git a/news/+pytest-plone.tests b/news/+pytest-plone.tests new file mode 100644 index 0000000..3567244 --- /dev/null +++ b/news/+pytest-plone.tests @@ -0,0 +1 @@ +Reused the built-in `anon_request` and `functional_portal` fixtures from pytest-plone 1.0.0 instead of the local re-implementations. @ericof diff --git a/tests/services/conftest.py b/tests/services/conftest.py index b900877..d9878f0 100644 --- a/tests/services/conftest.py +++ b/tests/services/conftest.py @@ -1,6 +1,3 @@ -from plone.restapi.testing import RelativeSession -from zope.component.hooks import setSite - import pytest @@ -10,22 +7,5 @@ def http_request(restapi): @pytest.fixture() -def portal(restapi): - portal = restapi["portal"] - setSite(portal) - yield portal - - -@pytest.fixture() -def request_api_factory(portal): - def factory(): - url = portal.absolute_url() - api_session = RelativeSession(f"{url}/++api++") - return api_session - - return factory - - -@pytest.fixture() -def api_anon_request(request_api_factory): - return request_api_factory() +def functional_portal(restapi): + yield restapi["portal"] diff --git a/tests/services/test_services_authomatic.py b/tests/services/test_services_authomatic.py index 85ce8df..526dc00 100644 --- a/tests/services/test_services_authomatic.py +++ b/tests/services/test_services_authomatic.py @@ -5,8 +5,8 @@ class TestServiceAuthomaticGet: @pytest.fixture(autouse=True) - def _setup(self, api_anon_request): - self.api_session = api_anon_request + def _setup(self, anon_request): + self.api_session = anon_request @pytest.mark.parametrize( "url,error_type,error_message", diff --git a/tests/services/test_services_login.py b/tests/services/test_services_login.py index 89d54d1..ddc6977 100644 --- a/tests/services/test_services_login.py +++ b/tests/services/test_services_login.py @@ -3,8 +3,8 @@ class TestServiceLogin: @pytest.fixture(autouse=True) - def _setup(self, api_anon_request): - self.api_session = api_anon_request + def _setup(self, anon_request): + self.api_session = anon_request def test_get_login_endpoint(self): response = self.api_session.get("/@login") From e480067957f80624562117b6e3c8b70e5fb86f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Fri, 10 Jul 2026 17:46:56 -0300 Subject: [PATCH 05/10] Update build tooling and editor configuration --- .vscode/extensions.json | 3 ++- .vscode/settings.json | 4 +++- Makefile | 39 ++++++++++++++++++++------------------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 37c0a82..3c82942 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,7 @@ { "recommendations": [ "charliermarsh.ruff", - "ms-python.python" + "ms-python.python", + "ms-python.vscode-python-envs" ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 21ae9f6..4669c17 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,8 @@ { - "flake8.args": ["--config=pyproject.toml"], "ruff.organizeImports": true, + "python-envs.workspaceSearchPaths": [ + ".venv" + ], "python.terminal.activateEnvironment": true, "python.testing.pytestArgs": [ "tests" diff --git a/Makefile b/Makefile index e11c90f..dbb690c 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,15 @@ BACKEND_FOLDER=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) ifdef PLONE_VERSION PLONE_VERSION := $(PLONE_VERSION) else -PLONE_VERSION := 6.1.1 +PLONE_VERSION := 6.2.1 +endif + +export PYTHON_VERSION := 3.14 + +ifdef CI +UV_VENV_ARGS := +else +UV_VENV_ARGS := --python=$(PYTHON_VERSION) endif VENV_FOLDER=$(BACKEND_FOLDER)/.venv @@ -47,27 +55,14 @@ all: build help: ## This help message @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' -############################################ -# Config -############################################ -instance/etc/zope.ini instance/etc/zope.conf: ## Create instance configuration - @echo "$(GREEN)==> Create instance configuration$(RESET)" - @uvx cookiecutter -f --no-input -c 2.1.1 --config-file instance.yaml gh:plone/cookiecutter-zope-instance - -.PHONY: config -config: instance/etc/zope.ini - -############################################ -# Installation -############################################ -requirements-mxdev.txt: ## Generate constraints file +requirements-mxdev.txt: pyproject.toml mx.ini ## Generate constraints file @echo "$(GREEN)==> Generate constraints file$(RESET)" @echo '-c https://dist.plone.org/release/$(PLONE_VERSION)/constraints.txt' > requirements.txt - @uvx mxdev -c mx.ini + @uvx 'mxdev[uv]' -c mx.ini $(VENV_FOLDER): requirements-mxdev.txt ## Install dependencies @echo "$(GREEN)==> Install environment$(RESET)" - @uv venv $(VENV_FOLDER) + @if [[ -d "$(VENV_FOLDER)" ]]; then echo "$(YELLOW)==> Environment already exists at $(VENV_FOLDER)$(RESET)"; else uv venv $(UV_VENV_ARGS) $(VENV_FOLDER); fi @uv pip install -r requirements-mxdev.txt .PHONY: sync @@ -75,14 +70,20 @@ sync: $(VENV_FOLDER) ## Sync project dependencies @echo "$(GREEN)==> Sync project dependencies$(RESET)" @uv pip install -r requirements-mxdev.txt +instance/etc/zope.ini instance/etc/zope.conf: instance.yaml ## Create instance configuration + @echo "$(GREEN)==> Create instance configuration$(RESET)" + @uvx cookiecutter -f --no-input -c 2.4.1 --config-file instance.yaml gh:plone/cookiecutter-zope-instance + +.PHONY: config +config: instance/etc/zope.ini + .PHONY: install install: $(VENV_FOLDER) config ## Install Plone and dependencies .PHONY: clean clean: ## Clean installation and instance @echo "$(RED)==> Cleaning environment and build$(RESET)" - @rm -rf $(VENV_FOLDER) pyvenv.cfg .installed.cfg instance .venv .pytest_cache .ruff_cache constraints* requirements* - $(MAKE) -C "./docs" clean + @rm -rf $(VENV_FOLDER) pyvenv.cfg .installed.cfg instance/etc .venv .pytest_cache .ruff_cache constraints* requirements* ############################################ # Instance From 5ec274cd680043063a0f88ee61cc720a5a8e72d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Fri, 10 Jul 2026 17:48:16 -0300 Subject: [PATCH 06/10] Bump version to 3.0.0.dev0 --- src/pas/plugins/authomatic/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pas/plugins/authomatic/__init__.py b/src/pas/plugins/authomatic/__init__.py index 2962bf3..9ffc1c3 100644 --- a/src/pas/plugins/authomatic/__init__.py +++ b/src/pas/plugins/authomatic/__init__.py @@ -3,7 +3,7 @@ import logging -__version__ = "2.0.1.dev0" +__version__ = "3.0.0.dev0" PACKAGE_NAME = "pas.plugins.authomatic" From 2915ac5168f54e71d6cc2005b0da10dabda169b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Fri, 10 Jul 2026 17:52:13 -0300 Subject: [PATCH 07/10] Disable fail-fast in the CI test matrix --- .github/workflows/main.yml | 1 + news/+fail-fast.internal | 1 + 2 files changed, 2 insertions(+) create mode 100644 news/+fail-fast.internal diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e639a66..55aa530 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,6 +22,7 @@ jobs: needs: - config strategy: + fail-fast: false matrix: python-version: ["3.14", "3.13", "3.12", "3.11"] plone-version: ["6.2-latest", "6.1-latest"] diff --git a/news/+fail-fast.internal b/news/+fail-fast.internal new file mode 100644 index 0000000..d4e28dc --- /dev/null +++ b/news/+fail-fast.internal @@ -0,0 +1 @@ +Disabled `fail-fast` in the CI test matrix so a single failing job no longer cancels the others. @ericof From c290e7f834c64d3bf2d6a041d16e1ba57be48c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Fri, 10 Jul 2026 17:58:09 -0300 Subject: [PATCH 08/10] Exclude unsupported Python 3.14 / Plone 6.1 from CI matrix --- .github/workflows/main.yml | 17 +++++++++++++++-- news/+matrix.internal | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 news/+matrix.internal diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 55aa530..d3542e5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,8 +24,21 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.14", "3.13", "3.12", "3.11"] - plone-version: ["6.2-latest", "6.1-latest"] + include: + - python-version: "3.14" + plone-version: "6.2-latest" + - python-version: "3.13" + plone-version: "6.2-latest" + - python-version: "3.12" + plone-version: "6.2-latest" + - python-version: "3.11" + plone-version: "6.2-latest" + - python-version: "3.13" + plone-version: "6.1-latest" + - python-version: "3.12" + plone-version: "6.1-latest" + - python-version: "3.11" + plone-version: "6.1-latest" with: python-version: ${{ matrix.python-version }} plone-version: ${{ matrix.plone-version }} diff --git a/news/+matrix.internal b/news/+matrix.internal new file mode 100644 index 0000000..5e696e3 --- /dev/null +++ b/news/+matrix.internal @@ -0,0 +1 @@ +Excluded the unsupported Python 3.14 / Plone 6.1 combination from the CI test matrix. @ericof From 3393c86f9d883fe93b85dbc716d9f75b218e8f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Fri, 10 Jul 2026 18:14:25 -0300 Subject: [PATCH 09/10] Update README for the new Python and Plone baselines --- README.md | 16 +++++++++------- news/+readme.documentation | 1 + 2 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 news/+readme.documentation diff --git a/README.md b/README.md index 8a12e1a..405df1e 100644 --- a/README.md +++ b/README.md @@ -205,7 +205,7 @@ There are some differences in configuration: ## Integration with Entra ID -Enumeration PAS plugin: if you're using **pas.plugins.authomatic** with *Microsoft Entra ID*, we recommend pairing it with [pas.plugins.eea](https://github.com/eea/pas.plugins.eea) for proper user enumeration and metadata synchronization. This complementary plugin enables listing all the Entra ID users and groups and is compatible with both Plone 5 and Plone 6. +Enumeration PAS plugin: if you're using **pas.plugins.authomatic** with *Microsoft Entra ID*, we recommend pairing it with [pas.plugins.eea](https://github.com/eea/pas.plugins.eea) for proper user enumeration and metadata synchronization. This complementary plugin enables listing all the Entra ID users and groups and is compatible with Plone 6.1 and 6.2. ## Source Code and Contributions @@ -222,7 +222,7 @@ We appreciate any contribution and if a release is needed to be done on PyPI, pl ### Development -You need a working `python` environment (system, virtualenv, pyenv, etc) version 3.7 or superior. +You need a working `python` environment (system, virtualenv, pyenv, etc) version 3.11 or superior. Then install the dependencies and a development instance using: @@ -246,9 +246,9 @@ By default we use the latest Plone version in the 6.x series. ### Changelog entries -The `CHANGES.md` file is managed using [towncrier](https://towncrier.readthedocs.io/). All non trivial changes must be accompanied by an entry in the `news` directory. Using such a tool instead of editing the file directly, has the following benefits: +The `CHANGELOG.md` file is managed using [towncrier](https://towncrier.readthedocs.io/). All non trivial changes must be accompanied by an entry in the `news` directory. Using such a tool instead of editing the file directly, has the following benefits: -* It avoids merge conflicts in CHANGES.md. +* It avoids merge conflicts in CHANGELOG.md. * It avoids news entries ending up under the wrong version header. The best way of adding news entries is this: @@ -260,12 +260,14 @@ The best way of adding news entries is this: * For bug fixes: 42.bugfix. * For new features: 42.feature. * For internal changes: 42.internal. - * For breaking changs: 42.breaking. + * For breaking changes: 42.breaking. + * For documentation changes: 42.documentation. + * For test changes: 42.tests. * Any other extensions are ignored. -* The contents of this file should be markdown formatted text that will be used as the content of the CHANGES.md entry. +* The contents of this file should be markdown formatted text that will be used as the content of the CHANGELOG.md entry. -Towncrier will automatically add a reference to the issue when rendering the CHANGES.md file. +Towncrier will automatically add a reference to the issue when rendering the CHANGELOG.md file. ### Releasing `pas.plugins.authomatic` diff --git a/news/+readme.documentation b/news/+readme.documentation new file mode 100644 index 0000000..b39aaa6 --- /dev/null +++ b/news/+readme.documentation @@ -0,0 +1 @@ +Updated the README: bumped the minimum Python to 3.11, corrected the changelog filename to `CHANGELOG.md`, and documented the `documentation` and `tests` news fragment types. @ericof From 0c5dc7f315d60e98f8d90182a038eb58f8b79bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89rico=20Andrei?= Date: Fri, 10 Jul 2026 18:17:10 -0300 Subject: [PATCH 10/10] Run the CI coverage job in parallel with the test matrix --- .github/workflows/main.yml | 1 - news/+coverage.internal | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 news/+coverage.internal diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d3542e5..3f75586 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,7 +48,6 @@ jobs: uses: plone/meta/.github/workflows/backend-pytest-coverage.yml@2.x needs: - config - - test with: python-version: ${{ needs.config.outputs.python-version }} plone-version: ${{ needs.config.outputs.plone-version }} diff --git a/news/+coverage.internal b/news/+coverage.internal new file mode 100644 index 0000000..c95cbd3 --- /dev/null +++ b/news/+coverage.internal @@ -0,0 +1 @@ +Ran the CI coverage job in parallel with the test matrix instead of waiting for it to finish. @ericof