Migrate your existing package with scikit-package
Prerequisites
This guide is for developers who have an existing Python package under Git control and want to migrate it to the Level 5 scikit-package
standard.
We assume you have experience creating a package using scikit-package
Level 4 and 5. We also assume you are familiar with the forking workflow on GitHub.
See also
If you are not familiar with contributing via forking, please read What is the general the workflow?.
Tips and how to receive support
We understand that migration can be challenging. We offer many ways to help you guide through the process:
You may cross-check with the Billinge group’s up-to-date package,
diffpy.utils
: https://github.com/diffpy/diffpy.utils.We provide Frequently asked questions (FAQ) describing design decisions and how to override them in the
scikit-package
template.After you’ve cross-checked and searched through the documentation (tutorials, examples, FAQs) please feel free to ask questions by creating an issue in the GitHub repository here.
Install scikit-package
with conda
Ensure that
conda
is installed on your local computer as instructed in (Required) Use conda environment to install packages and run Python code.Ensure that you have added the
conda-forge
channel to yourconda
configuration.$ conda config --add channels conda-forge
Create a new conda environment
skpkg-env
and installscikit-package
andpre-commit
simultaneously by running the following command:$ conda create -n skpkg-env scikit-package pre-commit
Note
If the above command does not work, ensure you have added the
conda-forge
channel to yourconda
configuration in Step 2.Activate the environment:
$ conda activate skpkg-env
Confirm that you have the latest version of
scikit-package
available on GitHub:$ pip show scikit-package
Step 1. Pre-commit workflow
Clone the repository and set
upstream
to the original repository.$ git clone <URL-of-the-forked-repo> $ cd <package-name> $ git remote add upstream <URL-of-the-original-repo>
Note
Are you the creator of the repository? You can type
origin
instead ofupstream
in the rest of the tutorial, e.g.,git pull origin main
instead ofgit pull upstream main
. Here, we assume a forking workflow.Is your default branch called
master
? Rungit pull upstream master
throughout the guide instead. However, please note thatmain
is the default branch name for GitHub.
Run black
in your codebase
Create a new branch called
black-edits
. This branch will be used to applyblack
to all files in the old project directory:$ git checkout main $ git pull upstream main
Activate the conda environment and install
black
:$ conda activate skpkg-env $ conda install black
Create a new branch called
black-edits
and create a new file calledpyproject.toml
:$ git checkout -b black-edits $ touch pyproject.toml
Copy and paste the following content at the bottom of
pyproject.toml
:[tool.black] line-length = 79 include = '\.pyi?$' exclude = ''' /( \.git | \.hg | \.mypy_cache | \.tox | \.venv | \.rst | \.txt | _build | buck-out | build | dist | blib2to3 | tests/data )/
Lint the code:
$ black .
See also
To skip certain files, add them under the
exclude
section in thepyproject.toml
.Push the changes to the
black-edits
branch:$ git add . $ git commit -m "skpkg: apply black to all files in the project directory" $ git push origin black-edits
Create a PR from
username/black-edits
toupstream/main
.The PR title can be
skpkg: apply black line-length 79 to all files in the project directory
.Review and wait for the PR to be merged to
upstream/main
. If you are the project maintainer, you can merge the PR yourself.Done!
Apply pre-commit auto-fixes without manual edits
Sync with the
upstream/main
branch:$ git checkout main && git pull upstream main
Create a new branch called
pre-commit-auto
:$ git checkout -b pre-commit-auto
Create a new package using
scikit-package
:$ package create public
Copy the
pre-commit
configuration files from the new to the old directory:$ cp <package-name>/.pre-commit-config.yaml . $ cp <package-name>/.isort.cfg . $ cp <package-name>/.flake8 .
Trigger hooks and auto-fixes without manual edits:
$ pre-commit run --all-files
Add the changes to the
pre-commit-auto
branch:$ git add . && git commit -m "style: apply pre-commit hooks with no manual edits"``
Push the changes to the remote repository:
$ git push origin pre-commit-auto
Create a PR from
username/pre-commit-auto
toupstream/migration
. The PR title can beskpkg: apply pre-commit to project directory with no manual edits
.Note
The new
upstream/migration
branch can be created by the project maintainer or owner. On the main page of the upstream repository, click and typemigration
. This will create a new branch calledmigration
.Wait for the PR to be merged to
upstream/migration
branch.
Apply manual edits to pass pre-commit
hooks
The package will most likely have failed pre-commit
hooks. We will manually fix the errors raised by flake8
, codespell
, etc.
Note
Do you have no pre-commit errors after running pre-commit run --all-files
? Great! You can skip this section and move on to the next section.
Here, instead of fixing all errors at once, we will address each type of error one at a time. For example, a branch called pre-commit-spelling
may contain spelling fixes, while another branch, pre-commit-flake8-line
fixes of line length errors raised by flake8.
Sync with the
upstream/migration
branch:$ git checkout migration $ git pull upstream migration
Create a new branch that will be used to fix the type of errors:
$ git checkout -b pre-commit-<theme>
Run
pre-commit run --all-files
to see the errors:See also
Do you want to ignore certain files/folders and also set the preferred line-length? Visit Pre-commit in the FAQ section to learn how to customize line-lenghts, ignore certain errors, and skip certain files and paths.
If you are suppressing
flake8
errors, you can create GitHub issues to resolve them after migration.Fix the errors manually for the specific theme.
Once you are done with fixing the type of errors commit, push the changes to your branch
$ git add <files-modified-to-fix-error> $ git commit -m "skpkg: fix <theme> errors" $ git push origin pre-commit-<theme>
Create a PR from
username/pre-commit-<theme>
toupstream/migration
. The PR title can beskpkg: fix <theme> errors
.Wait for the PR to be merged to
upstream/migration
branch.Repeat for other themes of errors, always pull the latest commits from
upstream/migration
before creating a new branch:$ git checkout migration $ git pull upstream migration $ git checkout -b pre-commit-<another-theme>
Are all the PRs merged and do all
pre-commit
hooks pass? If so, you are ready for the next section! Before that, let’s automatically triggerpre-commit
hooks going forward:$ pre-commit install
Setup pre-commit CI
Now, we want to ensure pre-commit hooks are also executed when a pull request is made in the remote repository.
Visit https://github.com/apps/pre-commit-ci and click Configure.
Select the repository(s).
Done!
Step 2. Migration workflow
Let’s first migrate the essential files from the old project to the new project directory.
Attention
Please read the following carefully before proceeding:
Please Do NOT delete/remove any files before confirming that it is absolutely unnecessary. If you are unsure, contact the project maintainer first.
Please Do NOT delete project-specific content such as project descriptions in README, license information, authors, tutorials, examples.
Move essential files to run local tests
Pull the latest commits from
upstream/migration
$ git checkout migration && git pull upstream migration
Move into the new directory created by
scikit-package
:$ cd <package-name>
Move
.git
from the old (..
) to the new directory (.
):$ mv ../<package-name>/.git .
See a list of files that have been (1) untracked, (2) deleted, (3) modified:
$ git status
See also
untracked
are new files created byscikit-package
.deleted
are files in the old directory but the files that are not in the new directory. At the moment, most of thesrc
andtests
anddoc
files will be in this category. We will move them from the old to the new directory in the next few steps.modified
are files that that exist both in the old and the new directory, while the scikig-package has made changes to them.
Create a new branch called called
setup-CI
:git checkout -b setup-CI
Now you will move
src
andtests
folders in the following steps.Copy files
$ cp -n -r ../src . $ cp -n -r ../tests .
See also
The
-n
option is used to prevent overwriting existing files in the destination directory. If you want to overwrite existing files, remove the-n
option.Confirm the
src
andtests
files that showed asdeleted
are no longer in thedeleted
.$ git status
Commit the changes:
$ git add src && git commit -m "skpkg: mirate src folder" $ git add tests && git commit -m "skpkg: migrate tests folder"
Manually list the dependencies under
requirements/pip.txt
,requirements/tests.txt
,requirements/docs.txt
,requirements/conda.txt
.Delete
requirements/build.txt
if your package only contains Python code.$ rm requirements/build.txt
Add and commit the changes in the
requirements
folder:$ git add requirements $ git commit -m "skpkg: list dependencies in requirements folder"
Test your package from a new conda environment:
$ conda create -n <package-name>-env python=3.13 \ --file requirements/conda.txt \ --file requirements/test.txt $ conda activate <package-name>-env $ pip install -e . --no-deps $ pytest
Note
Include
--file requirements/build.txt
if it exists.Congratulations! After the tests pass, let’s now setup GitHub Actions in the following section.
Setup repository
We want to run GitHub Actions, in order to do so
Setup GitHub Actions
Add and commit the files in the
.github
folder:$ git add .github/workflows/tests-on-pr.yml .gitignore $ git commit -m "skpkg: add CI and issue/PR templates"
Attention
If your package does not support the latest Python version of 3.13, you will need to specify the Python version supported by your package. Follow the instructions here to set the Python version under
.github/workflows
in In Level 5, How do I set different Python versions for GitHub CI?.Add and commit the
requirements
folder:git add requirements git commit -m "skpkg: list dependencies in requirements folder"
Add and commit
pyproject.toml
:git add pyproject.toml git commit -m "skpkg: add pyproject.toml"
Push the changes to the
setup-CI
branch:git push origin setup-CI
Create a PR from
username/setup-CI
toupstream/migration
.The pull request title can be
skpkg: setup CI after migrating tests, src, requirements, and .github folder
.Wait for review after CI passes.
Once the PR is merged, let’s upload other files.
Add configuration files
Pull the latest commits from
upstream/migration
and create a new branch calledconfig
:$ git checkout migration $ git pull upstream migration $ git checkout -b config
Add and commit configuration files:
$ git add .pre-commit-config.yaml .codespell .flake8 .isort.cfg $ git commit -m "skpkg: add config files for pre-commit " $ git add .readthedocs.yaml .codecov.yml .github $ git commit -m "skpkg: add config files readthedocs, codecov, GitHub"
Create a PR from
username/config
toupstream/migration
.The PR title can be
skpkg: add configuration files for pre-commit, readthedocs, codecov
.Once the PR is merged, move to the next section.
Move documentation files
Pull the latest commits from
upstream/migration
and create a new branch calleddoc
:$ git checkout migration $ git pull upstream migration $ git checkout -b doc
Copy documentation from the old to the new repository:
$ cp -n -r ../doc/source/* ./doc/source.
Note
If files are moved to a different path like
doc/manual/source
(old) todoc/source
(new), open the project in IDE and do a global search (ctrl + shift + f) for../
or..
and modify all relative path instances.Ensure the documentation can be built locally:
$ conda install --file requirements/docs.txt $ cd doc && make html & open _build/html/index.html
Add and commit the changes:
$ git add doc $ git commit -m "skpkg: migrate documentation"
By hand, migrate content over to
README.rst
.Note
In Level 5, we provide a rich template for
README.rst
instead of usingREADME.md
. If you already had a richREADME.md
in Level 4, you can use a tool to convert.md
to.rst
. For example, you may use this free CloudConvert tool.Add other public facing static files:
$ git add AUTHORS.rst CHANGELOG.rst CODE_OF_CONDUCT.rst LICENSE.rst $ git commit -m "skpkg: add config files for authors, changelog, code of conduct, license" $ git add MANIFEST.in $ git commit -m "skpkg: add MANIFEST.in" $ git add README.rst $ git commit -m "skpkg: add README.rst"
Create a news file:
$ cp news/TEMPLATE.rst news/doc.rst
In
news/docs..rst
, add the following content underFixed:
:**Added:** * <news item> **Fixed:** * Support ``scikit-package`` Level 5 standard (https://scikit-package.github.io/scikit-package/).
Add the news files:
$ git add news $ git commit -m "skpkg: add news files"
Create a PR from
usernmae/doc
toupstream/migration
.The PR title can be
skpkg: migrate documentation, README, and public static files
.Once the PR is merged to
upstream/main
, move to the final step!
Step 3. Final check
Review the following items:
All the badges on
README.rst
are passing.LICENSE.rst
is verified as correct.Locally rendered documentation contains all appropriate pages, tutorials, and other human-written text is up-to-date with any changes in the code.
Installation instructions in the
README.rst
, documentation, and the website are updated.Successfully run any tutorial examples or do functional testing with the latest Python version.
Grammar and writing quality are checked (no typos).
Ask the project maintainer to create a PR from
upstream/migration
toupstream/main
After the PR is merged to
upstream/main
, archive the old repository by naming it:$ mv <package-name> <package-name>-archive
Clone the latest version of the package from the remote:
$ cd ~/dev $ git clone <URL-of-the-forked-repo> $ git remote add upstream <URL-of-the-original-repo> $ git pull upstream main
Now, you should be able to run the following to test your package!
$ conda activate <package-name>-env $ pytest $ pre-commit run --all-files
Congratulations! You are done with migration!
Ready for release?
Are you ready to release your package to PyPI and conda-forge? Let’s start from Publish on GitHub and to PyPI!