Skip to content

Commit ea7e8c2

Browse files
committed
feat: explain how to switch to add native namespace
To go along with the PLIP 3928.
1 parent 5b06227 commit ea7e8c2

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
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 end of 2025.
12+
13+
[PLIP 3928](https://github.com/plone/Products.CMFPlone/issues/3928) is tracking 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+
Clone the repository or ensure you are at latest changes:
25+
26+
```shell
27+
git clone git@github.com:plone/$package
28+
cd $package
29+
# or update
30+
git fetch -p
31+
git checkout main # or master
32+
git rebase
33+
```
34+
35+
Find out what's the last release and create a branch for it:
36+
37+
```shell
38+
# list all tags
39+
git for-each-ref --sort=taggerdate --format '%(tag)'
40+
# get the last tag's major number
41+
MAJOR=`git for-each-ref --sort=taggerdate --format '%(tag)' | tail -n1 | cut -d"." -f1`
42+
# create a branch for it
43+
git checkout -b $MAJOR.x
44+
# push the newly created branch
45+
git push $MAJOR.x
46+
```
47+
48+
### Update buildout.coredev
49+
50+
!!! note
51+
Only relevant for Plone core packages
52+
53+
Update `buildout.coredev`'s branch 6.1 to use the newly created branch
54+
55+
```shell
56+
# go to the repository or clone it
57+
cd buildout.coredev
58+
# ensure you are at latest changes
59+
git fetch -p
60+
git checkout 6.1
61+
git rebase
62+
# update the branch being used by the python distribution
63+
sed -i "s/$package.git branch=master/$package.git branch=$MAJOR.x/" sources.cfg
64+
# add the changes, commit and push
65+
git add sources.cfg
66+
git commit -m"chore: use branch $MAJOR.x for $package"
67+
git push
68+
```
69+
70+
!!! note
71+
To lower the amount of builds in Jenkins, either do a few at a time or add a `[ci-skip]` on the commit message
72+
73+
### Numbers before
74+
75+
One risk of changing to the native namespaces is that some files, or tests, might not be left behind.
76+
77+
To ensure all tests and files are kept after the switch, gather the numbers before the change:
78+
79+
Get the list of tests:
80+
81+
```shell
82+
tox run -e test -- --list-tests
83+
```
84+
85+
!!! note
86+
Adapt to whichever way you are using to run the tests.
87+
The above is meant for repositories that follow `plone.meta` conventions.
88+
The `--list-tests` comes from `zope.testrunner`, if you are using that but not `plone.meta` you can use that as well.
89+
90+
Create a distribution to get a listing of how many files are currently packaged:
91+
92+
```shell
93+
uvx --from build pyproject-build
94+
```
95+
96+
A `dist` folder is created with two archives in it: a `.tar.gz` and a `.whl`.
97+
98+
To get the number of files on them run the following commands:
99+
100+
```shell
101+
python -c "import tarfile; print(len(tarfile.open('dist/$package.tar.gz', 'r:gz').getnames()))"
102+
python -c "from zipfile import ZipFile; print(len(ZipFile('dist/$package.whl').namelist()))"
103+
```
104+
105+
Keep these numbers around for later.
106+
107+
### Build backend
108+
109+
To ensure the python continues to build, ensure that `setuptools` is defined as its build backend.
110+
111+
For that inspect the `pyproject.toml`, it should have these lines:
112+
113+
```toml
114+
[build-system]
115+
requires = ["setuptools>=68.2,<80", "wheel"]
116+
```
117+
118+
If they are not there, add them, commit and push the changes.
119+
120+
### Convert to native namespace
121+
122+
Use `plone.meta`'s `switch-to-pep420` script:
123+
124+
```shell
125+
cd $package
126+
uvx --from plone.meta switch-to-pep420 .
127+
```
128+
129+
### Update the test matrix
130+
131+
!!! note
132+
Only relevant for Plone core packages
133+
134+
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.
135+
136+
Thus, we need to ensure that the test matrix, only tests it against this Plone version.
137+
138+
For that, update `.meta.toml` with the following changes:
139+
140+
```toml
141+
[tox]
142+
test_matrix = {"6.2" = ["*"]}
143+
```
144+
145+
And update the scaffolding files with `plone.meta`:
146+
147+
```shell
148+
uvx --from plone.meta config-package .
149+
```
150+
151+
Review the changes and ensure all changes are sound.
152+
153+
!!! note
154+
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.
155+
156+
### Compare numbers
157+
158+
Get the list of tests, like before and compare the lists to ensure that the same amount of tests are found.
159+
160+
```shell
161+
tox run -e test -- --list-tests
162+
```
163+
164+
Likewise, create the distribution files and compare the numbers with the previous run:
165+
166+
```shell
167+
python -c "import tarfile; print(len(tarfile.open('dist/$package.tar.gz', 'r:gz').getnames()))"
168+
python -c "from zipfile import ZipFile; print(len(ZipFile('dist/$package.whl').namelist()))"
169+
```
170+
171+
If all numbers match, review the changes once more, push the branch with the changes for others to review it.

0 commit comments

Comments
 (0)