Skip to content

Commit def1b04

Browse files
committed
feat: explain how to switch to add native namespace
To go along with the PLIP 3928.
1 parent 2ea23ff commit def1b04

File tree

2 files changed

+189
-0
lines changed

2 files changed

+189
-0
lines changed

docs/developer-guide/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ You can help consolidate all of development documentation here, even if it is to
2424
develop-volto-add-ons-index
2525
create-a-distribution
2626
standardize-python-project-configuration
27+
native-namespaces
2728
```
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# Native namespace
2+
3+
This document explains the steps needed to convert a python distribution from `pkg_resources` namespace to native namespaces.
4+
5+
## Background
6+
7+
Python, since Python 3.3, added support for native namespaces, see [PEP 420](https://peps.python.org/pep-0420/).
8+
9+
Plone has been using `pkg_resources`-style namespaces, but they are deprecated in `setuptools`.
10+
11+
`setuptools` is planning to remove `pkg_resources`'s namespaces support by the end of 2025.
12+
13+
[PLIP 3928](https://github.com/plone/Products.CMFPlone/issues/3928) tracks the changes needed for Plone to adapt to the _new_ native namespaces.
14+
15+
## Steps
16+
17+
To convert a given (`$package`) python distribution to use native namespaces follow these steps.
18+
19+
### Create maintenance branch
20+
21+
!!! note
22+
Only relevant for Plone core packages
23+
24+
!!! tip
25+
This part is only needed when the `main` or `master` branch is used on multiple versions of the Plone core development buildout.
26+
27+
Clone the repository or ensure you are at latest changes:
28+
29+
```shell
30+
git clone git@github.com:plone/$package
31+
cd $package
32+
# or update
33+
git fetch -p
34+
git checkout main # or master
35+
git rebase
36+
```
37+
38+
Find out what's the last release and create a branch for it:
39+
40+
```shell
41+
# list all tags
42+
git for-each-ref --sort=taggerdate --format '%(tag)' refs/tags
43+
# get the last tag's major number
44+
MAJOR=`git for-each-ref --sort=taggerdate --format '%(tag)' refs/tags | tail -n1 | cut -d"." -f1`
45+
# create a branch for it
46+
git checkout -b $MAJOR.x
47+
# push the newly created branch
48+
git push
49+
```
50+
51+
### Update buildout.coredev
52+
53+
!!! note
54+
Only relevant for Plone core packages
55+
56+
Update `buildout.coredev`'s branch 6.1 to use the newly created branch
57+
58+
```shell
59+
# go to the repository or clone it
60+
cd buildout.coredev
61+
# ensure you are at latest changes
62+
git fetch -p
63+
git checkout 6.1
64+
git rebase
65+
# update the branch being used by the python distribution
66+
sed -i "s/$package.git branch=master/$package.git branch=$MAJOR.x/" sources.cfg
67+
# add the changes, commit and push
68+
git add sources.cfg
69+
git commit -m"chore: use branch $MAJOR.x for $package"
70+
git push
71+
```
72+
73+
Now check if you need to do the same on the 6.0 branch of `buildout.coredev`.
74+
75+
!!! tip
76+
You can use this [handy table](https://jenkins.plone.org/roboto/branches) to know which branch is used of a given package on each Plone version
77+
78+
!!! tip
79+
To lower the amount of builds in Jenkins, either do a few at a time or add a `[ci-skip]` on the commit message
80+
81+
### Numbers before
82+
83+
One risk of changing to the native namespaces is that some files, or tests, might be left behind.
84+
85+
To ensure all tests and files are kept after the switch, gather the numbers before the change:
86+
87+
Get the list of tests:
88+
89+
```shell
90+
tox run -e test -- --list-tests | wc -l
91+
```
92+
93+
!!! note
94+
Adapt to whichever way you are using to run the tests.
95+
The above is meant for repositories that follow `plone.meta` conventions.
96+
The `--list-tests` comes from `zope.testrunner`, if you are using that but not `plone.meta` you can use that as well.
97+
98+
Create a distribution to get a listing of how many files are currently packaged:
99+
100+
```shell
101+
uvx --from build pyproject-build
102+
```
103+
104+
A `dist` folder is created with two archives in it: a `.tar.gz` and a `.whl`.
105+
106+
To get the number of files on them run the following commands:
107+
108+
```shell
109+
python -c "import glob; import tarfile; print(len(tarfile.open(glob.glob('dist/*.tar.gz')[0], 'r:gz').getnames()))"
110+
python -c "import glob; from zipfile import ZipFile; print(len(ZipFile(glob.glob('dist/*.whl')[0]).namelist()))"
111+
```
112+
113+
Keep these numbers around for later.
114+
115+
### Build backend
116+
117+
To ensure the package continues to build, ensure that `setuptools` is defined as its build backend.
118+
119+
For that inspect the `pyproject.toml`, it should have these lines:
120+
121+
```toml
122+
[build-system]
123+
requires = ["setuptools>=68.2,<80", "wheel"]
124+
```
125+
126+
If they are not there, add them, commit and push the changes.
127+
128+
### Convert to native namespace
129+
130+
Use `plone.meta`'s `switch-to-pep420` script:
131+
132+
```shell
133+
cd $package
134+
uvx --from plone.meta switch-to-pep420 --no-tests .
135+
```
136+
137+
!!! tip
138+
This will also bump the version to a new major release.
139+
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.
140+
141+
### Update the test matrix
142+
143+
!!! note
144+
Only relevant for Plone core packages
145+
146+
As the switch to the native namespace has to 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.
147+
148+
Thus, we need to ensure that the test matrix, only tests against this Plone version.
149+
150+
For that, update `.meta.toml` with the following changes:
151+
152+
```toml
153+
[tox]
154+
test_matrix = {"6.2" = ["*"]}
155+
```
156+
157+
And update the scaffolding files with `plone.meta`:
158+
159+
```shell
160+
uvx --from plone.meta config-package --branch current .
161+
```
162+
163+
Review the changes and ensure all changes are sound.
164+
165+
!!! note
166+
If the diff is quite big, run `config-package` before all the changes, get that on a Pull Request, approved and merged and then do a follow up Pull Request to move to native namespace.
167+
168+
### Compare numbers
169+
170+
Get the list of tests, like before and compare the lists to ensure that the same amount of tests are found.
171+
172+
```shell
173+
tox run -e test -- --list-tests | wc -l
174+
```
175+
176+
Likewise, create the distribution files and compare the numbers with the previous run:
177+
178+
```shell
179+
python -c "import glob; import tarfile; print(len(tarfile.open(glob.glob('dist/*.tar.gz')[0], 'r:gz').getnames()))"
180+
python -c "import glob; from zipfile import ZipFile; print(len(ZipFile(glob.glob('dist/*.whl')[0]).namelist()))"
181+
```
182+
183+
It is okay if the numbers are slightly lower.
184+
For obvious reasons the old source distribution will have one or more extra `__init__.py` files.
185+
Both old distributions are expected to have an extra `namespace_packages.txt` file and possible an `x-nspkg.pth` file.
186+
If you lose more than a few files though, something is wrong.
187+
188+
If the numbers are close enough, review the changes once more, and push the branch with the changes for others to review it.

0 commit comments

Comments
 (0)