Native namespace#
This chapter is guide for how to convert a Python distribution from a pkg_resources namespace to a native namespace.
Python 3.3 added support for native namespaces. See PEP 420 for more details.
Plone has been using pkg_resources-style namespaces, but they are deprecated in setuptools.
setuptools is planning to remove pkg_resources's namespace support by the end of 2025.
PLIP 3928 tracks the changes needed for Plone to adapt to the new native namespaces.
To convert a given Python distribution to use a native namespace, follow these steps.
Create maintenance branch#
Note
This step is relevant only for Plone core packages.
Tip
This part is only needed when the main or master branch is used on multiple versions of the Plone core development buildout.
If you haven't cloned the package's repository, then do so.
git clone git@github.com:plone/$package
cd $package
Otherwise, pull the latest changes into your local repository.
git fetch -p
git checkout main # or master
git rebase
Find the last release tag, and create a branch for it.
List all tags.
git for-each-ref --sort=taggerdate --format '%(tag)' refs/tags
Get the last tag's major number.
MAJOR=`git for-each-ref --sort=taggerdate --format '%(tag)' refs/tags | tail -n1 | cut -d"." -f1`
Create a branch for it.
git checkout -b $MAJOR.x
Push the newly created branch.
git push
Update buildout.coredev#
Note
This step is relevant only for Plone core packages.
Update buildout.coredev's branch 6.1 to use the newly created branch.
cd buildout.coredev
Ensure you have the latest changes.
git fetch -p
git checkout 6.1
git rebase
Update the branch being used by the Python distribution.
sed -i "s/$package.git branch=master/$package.git branch=$MAJOR.x/" sources.cfg
Add the changes, commit, and push.
git add sources.cfg
git commit -m"chore: use branch $MAJOR.x for $package"
git push
Now check if you need to do the same on the 6.0 branch of buildout.coredev.
Tip
You can use this handy table to know which branch is used by a given package for each Plone version.
Tip
To lower the amount of builds in Jenkins, either do a few at a time or add a [ci-skip] on the commit message.
Counts before change#
There is a risk when changing to the native namespaces that some files, or tests, might be left behind. To ensure all tests and files are kept after the switch, gather the counts before the change.
tox run -e test -- --list-tests | wc -l
Note
Adapt to whichever way you are using to run the tests.
The above is meant for repositories that follow plone.meta conventions.
The --list-tests comes from zope.testrunner, if you are using that, but not plone.meta, although you can use that as well.
Create a distribution to get a listing of how many files are currently packaged.
rm -rf dist/
uvx --from build pyproject-build
A dist folder is created with two archives in it, one each with the file suffix of .tar.gz and .whl.
To get the count of files in them, run the following commands.
python -c "import glob; import tarfile; print(len(tarfile.open(glob.glob('dist/*.tar.gz')[0], 'r:gz').getnames()))"
python -c "import glob; from zipfile import ZipFile; print(len(ZipFile(glob.glob('dist/*.whl')[0]).namelist()))"
Note these counts for later in the step Compare counts after change.
Build backend#
To ensure the package continues to build, verify that setuptools is defined as its build backend.
For that, inspect the pyproject.toml.
It should have the following lines.
[build-system]
requires = ["setuptools>=68.2,<80", "wheel"]
If they are not there, then add them, commit, and push the changes.
Convert to native namespace#
Use plone.meta's switch-to-pep420 script.
cd $package
uvx --from plone.meta switch-to-pep420 --no-tests .
Tip
This will also bump the version to a new major release.
If the main or master branch is already an alpha version that is only used in Plone 6.2, you can specify that you don't want this version bump by adding the --no-breaking option.
Update the test matrix#
Note
This step is relevant only for Plone core packages.
Because the switch to the native namespace must be coordinated, all Python distributions need to be only for the same Plone version.
In this case, it was decided to do it for the Plone 6.2 version.
Thus, we need to ensure that the test matrix only tests against this Plone version.
For that, update .meta.toml with the following changes.
[tox]
test_matrix = {"6.2" = ["*"]}
Update the scaffolding files with plone.meta.
uvx --from plone.meta config-package --branch current .
Review the changes and ensure all changes are sound.
Note
If the diff is quite big, then run config-package before all the changes.
Get the result into a pull request, approved, and merged.
Then do a follow up pull request to move it to a native namespace.
Compare counts after change#
Get the list of tests, and compare this result to the earlier one to ensure the same test counts.
tox run -e test -- --list-tests | wc -l
Similarly, create the distribution files and compare the numbers with the previous run.
rm -rf dist/
uvx --from build pyproject-build
python -c "import glob; import tarfile; print(len(tarfile.open(glob.glob('dist/*.tar.gz')[0], 'r:gz').getnames()))"
python -c "import glob; from zipfile import ZipFile; print(len(ZipFile(glob.glob('dist/*.whl')[0]).namelist()))"
It is okay if the numbers are slightly lower.
For obvious reasons, the old source distribution will have one or more extra __init__.py files.
Both old distributions are expected to have an extra namespace_packages.txt file and possibly an x-nspkg.pth file.
If you lose more than a few files though, something is wrong.
If the numbers are close enough, review the changes once more, and push the branch with the changes for others to review it.