-
-
Notifications
You must be signed in to change notification settings - Fork 82
Development Methodology
Several projects in the CPython stdlib follow this methodology for development:
These projects are maintained primarily in their external repositories (sometimes referred to as "backports"). Development is preferred in the external repositories due to a host of advantages:
- The test suite runs under pytest, a richer test runner, affording more sophisticated behaviors even when running unittest-based tests.
- Maintenance follows best practices as defined by the skeleton used by hundreds of other projects, and deriving value from common concerns such as updating support for Python versions.
- Extra checks are performed to ensure consistent formatting, style, and safety (ruff, mypy, ...).
- Doctests are checked.
- Performance benchmarks can be measured and tested.
- Code is tested against all supported Python versions.
- Changes can be released quickly and get rapid feedback, shifting left the lifecycle.
- CPython is less strict so accepts changes more readily.
As a result, this preference means that the external projects are "upstream" of Python and code is synced "downstream" into Python's stdlib.
These projects still accept contributions downstream in Python. Issues can be tracked in either the CPython or the host project's repo. Maintainers will file additional issues when necessary for contributing changes.
Regardless of the original source of the contribution, these two codebases should be kept in close sync and utilize techniques to minimize the diffs between the two targets. Here are some of the ways these projects achieve that minimum variance:
- Code in the stdlib should be partitioned into folders pertaining to the shared functionality. That means that the abstract base classes for importlib resources should live in
importlib.resources.abc
and notimportlib.abc
. That is also whyzipfile.Path
is implemented aszipfile._path.Path
. - The external project should implement "compatibility" shims in separate modules or (preferably) packages. For example, importlib_resources exposes
future
andcompat
packages for the external-specific behaviors. This behavior is excluded in the port to CPython. - Each project keeps a
cpython
branch that tracks the state of the code that keeps track of the code in the same layout as it appears in the stdlib, such that one cancp -r
the contents in either direction and there should be no diff when projects are in sync.
- Check out the
cpython
branch of the external project (at $PROJECT). - Check out cpython to the
main
branch (at $CPYTHON). -
cp -r $(PROJECT) $(CPYTHON)
. - Ensure
git -C $(CPYTHON) diff
shows no diff. - If there is a diff, track down the source of the changes and determine how to reconcile.
- Ensure projects are in sync.
- In the
cpython
branch of the project, merge changes from main withgit merge main
. - Resolve conflicts. Some conflicts will be changes to deleted files that aren't needed for stdlib - just confirm the deletion. Other conflicts may be in code, so intelligently compare the changes for each branch.
- Ensure compatibility modules are not included. If new ones were added, delete them with
git rm -f path/to/compat
. - Replace references to compatibility modules with their stdlib equivalent.
- Search for references to the external package by name (e.g.
importlib_resources
) and replace them. - Commit the merge.
- Test the changes.
- Remove any incidental files (
git clean -fdx
). -
cp -r * $(CPYTHON)
. - Change directory to the CPython checkout.
- Build and test:
- Run the tests
./python.exe -m test.test_importlib -v
(or similar).
- Run the tests
- Address test failures in the external project, either in
cpython
ormain
(or another branch) as appropriate. Amend or commit or re-merge the changes to thecpython
branch and repeat "Test the changes."
- Remove any incidental files (
- Push the
cpython
branch of the external project. - Commit the changes and submit them for review following the usual CPython development process.
- If encountering issues with docs builds, consider running
make check suspicious html
in theDoc/
directory of CPython.
- If encountering issues with docs builds, consider running
The best way to sync from stdlib to external is to find the relevant squashed commit from CPython's main branch and cherry-pick it to the external project. Find the relevant commit (often from a relevant pull request merge message), $(COMMIT)
.
- Check out the project to the
main
branch. - Fetch the CPython repo with
git fetch https://github.com/python/cpython
. Maybe pass--depth 1000
so as not to fetch everything. This fetches the CPython repo into the external project's repo. - Cherry-pick the change with
git cherry-pick $(COMMIT)
.git
will most likely be able to associate the changes with the relevant files (even though they're in different locations).- Resolve creation/deletion conflicts (usually by electing to delete irrelevant files).
- Remove any files not relevant to this project (e.g.
git rm -rf Misc
for news fragments).
- (optional) Commit the merge as a checkpoint.
- Test the changes, make amendments or tweaks to make the code compatible, possibly as new commits.
- Push the changes.
- (optional)
git prune
to remove the CPython history. - Merge the changes into the
cpython
branch. - (optional) Check that projects are in sync.
In general, it's preferred for guidance documentation to be in CPython (only, not synced). The external projects should refer users to the CPython documentation. Some documentation (like API documentation from code and docstrings) is not viable in CPython, so will be hosted in the external project. Similarly, the changelog for the external project should be hosted by that project. Other documentation, like migration guides, might be maintained outside CPython.
Because CPython cannot reflect API documentation from code, it's possible API documentation may not be provided in CPython at all (due to the duplicative, toilsome work that entails), though contributors are welcome to provide it.