This repository contains a modern Python project managed entirely with Pixi, a reproducible and declarative environment manager.
All build and packaging metadata is consolidated in a single pyproject.toml
file, following modern Python packaging standards.
This project uses Pixi as the single tool for managing environments, dependencies, packaging, and task execution.
Follow the installation instructions from the Pixi website, or use:
curl -fsSL https://pixi.sh/install.sh | bash
Run the following command to create and activate the project environment with all dependencies:
pixi install
Use the following command to list all project-defined tasks:
pixi run
Example tasks:
build-pypi
: build the PyPI wheelbuild-conda
: build the Conda packagetest
: run the test suiteconda-publish
,pypi-publish
: publish the built artifactsclean-*
: clean build artifacts
Activate the Pixi environment:
pixi shell
Then, for development:
- Run tests:
pixi run test
- Run linting:
ruff check .
- Perform editable install:
pip install --no-deps -e .
This ensures your environment remains clean and all tasks are reproducible.
- π¦ Unified packaging for both PyPI and Conda via
pixi build
- π Python 3.11+ compatibility
- βοΈ Versioning handled by
versioningit
, derived from Git tags - π§ͺ Testing with
pytest
and code coverage reporting - π§Ό Linting & formatting with
ruff
- π Task automation via
pixi run
- π Supports CLI and optional GUI through modular structure in
src/packagenamepy/
-
Adjust the branch protection rules for the new repo. By default, we should protect the
main
(stable),qa
(release candidate), andnext
(development) branches.1.1 Go to the
Settings
tab of the new repo.1.2 Click on
Branches
on the left side.1.3 Click on
Add rule
button.1.4 Follow the instructions from Github.
-
Change the License if MIT license is not suitable for you project. For more information about licenses, please refer to Choose an open source license.
-
Adjust pre-commit configuration file,
.pre-commit-config.yaml
to enable/disable the hooks you need. For more information about pre-commit, please refer to pre-commit. -
Having code coverage,
codecov.yaml
is strongly recommended, please refer to Code coverage for more information. -
Adjust the GitHub Actions workflows for CI/CD to align with Pixi-only packaging. For more information about GitHub Actions, please refer to GitHub Actions.
-
Ensure that
.github/workflows/package.yaml
uses onlypixi run
commands for all build and publish steps. -
Validate that the following Pixi tasks are correctly invoked:
pixi run pypi-build
pixi run pypi-publish
pixi run conda-build
pixi run conda-publish
-
Remove or disable any steps using
conda-build
,python setup.py
, orpip install .
.
-
-
The legacy
conda.recipe/meta.yaml
is no longer needed since Conda packaging is now handled via Pixi andpyproject.toml
.- You may delete the
conda.recipe
folder entirely, unless it's still needed for backward compatibility with older workflows.
- You may delete the
-
Adjust
pyproject.toml
to match your project. For more information aboutpyproject.toml
, please refer to pyproject.toml.-
Specify package name at: pyproject.toml#L5
-
Specify package description at: pyproject.toml#L6
-
Specify any terminal entry points (terminal commands) at: pyproject.toml#30.
-
-
Adjust files for pixi
-
After updating your environment file, make sure to run
pixi install
and commit the updated lock file. -
Specify package name at: pyproject.toml#L65
In the example, invoking
packagename-cli
in a terminal is equivalent to running the python scriptfrom packagenamepy.packagename import main; main()
-
Projects will use a single
pyproject.toml
file to manage all the project metadata, including the project name, version, author, license, etc. -
Python has moved away from
setup.cfg
/setup.py
, and we would like to follow the trend for our new projects.
-
-
Specify package name at src/packagenamepy
-
Specify package name at: src/packagenamepy/packagename.py
-
If a GUI isn't used, delete the MVP structure at src/packagenamepy:
- mainwindow.py
- home/
- help/
-
Clear the content of this file and add your own README.md as the project README file. We recommend putting badges of the project status at the top of the README file. For more information about badges, please refer to shields.io.
Here we assume your intent is to upload the conda package to the anaconda.org/neutrons organization.
An administrator of anaconda.org/neutrons
must create an access token for your repository in the access settings.
After created, the token must be stored in a repository secret
:
- Navigate to the main page of the repository on GitHub.com.
- Click on the "Settings" tab.
- In the left sidebar, navigate to the "Security" section and select "Secrets and variables" followed by "Actions".
- Click on the "New repository secret" button.
- Enter
ANACONDA_TOKEN
for the secret name - Paste the Anaconda access token
- Click on the "Add secret" button
- Test the setup by creating a release candidate tag,
which will result in a package built and uploaded to
https://anaconda.org/neutrons/mypackagename
Follow the instructions in the Confluence page to create the access token.
Both PyPI and Conda packages are supported. All build and publishing steps are defined in Pixi tasks.
Note that if your project is not being built and published to PyPI, you can safely modify the pyproject.toml
to remove any pixi tasks related to PyPI, and the hatch
dependency.
Similarly, if you are not publishing to conda, you can remove any related dependencies, configurations, and tasks.
-
Ensure you have access to the project on PyPI.
-
Clean working directory:
git status
should be clean. -
Run the Pixi task to build the wheel:
pixi run pypi-build
-
Check the wheel for issues manually:
twine check dist/*
-
Upload to TestPyPI:
pixi run pypi-publish-test
Ensure your
~/.pypirc
contains the correct token:[distutils] index-servers = pypi testpypi [testpypi] repository = https://test.pypi.org/legacy/ username = __token__ password = YOUR_TESTPYPI_TOKEN
-
Install from TestPyPI to verify:
pip install --index-url https://test.pypi.org/simple/ examplepyapp
-
When ready, trigger the GitHub Action (
package.yaml
) to upload to PyPI.
-
Ensure the target channel is correct in
.github/workflows/package.yaml
. -
Run the Pixi build:
pixi run conda-build
This creates a
.conda
package in the project root. -
Publish using:
pixi run conda-publish
Ensure the
ANACONDA_TOKEN
secret is configured in GitHub for CI/CD to work.
-
By default, we recommend using
pixi install
to set up the development environment. This will create a virtual environment in the.pixi
directory at the root of the repository. -
If you prefer to use a detached environment, set the
detached-environments
option totrue
in.pixi/config.toml
:pixi config set detached-environments true
-
If you want to keep your environment between sessions, add the following line to your
.bashrc
or.bash_profile
:export PIXI_CACHE_DIR="$HOME/.pixi/cache"
-
After setting up the environment, you can activate it with:
pixi shell
-
If you are using VSCode as your IDE, we recommend to start code with
pixi run code .
to ensure the correct environment is inherited by the IDE. Alternatively, you can specify the Python interpreter path usingCtrl + Shift + P
and searching for "Python: Select Interpreter", or manually editing the.vscode/settings.json
file to set the Python interpreter path:{ "python.pythonPath": ".pixi/venv/bin/python" }
The tool pip-audit
allows for checking dependencies for versions with known weaknesses or vulnerabilities as registered in open source vulnerabilities database (osv).
This is provided as the task audit-deps
which will verify that there are no known python dependencies in the pixi environment.
Finding source of issue: This is an outdated example used to demonstrate how to suppress vulnerabilities.
Assume that pixi run audit-deps
returns a message that there is a issue PYSEC-2025-61 that is associated with pillow v11.2.0.
Since this is an indirect dependency, one can use
$ pixi tree --invert pillow
pillow 11.2.0
βββ anaconda-client 1.13.0
to find out that this is included by the anaconda-client package which is also not a runtime dependency. This can be ignored.
Ignoring a vulnerability: Unfortunately, pip-audit
does not have a configuration file that allows for ignoring issues.
This is done with a suppression in the pyproject.toml
by modifying the task.
# ignore pillow error because it is only used by anaconda-client v1.13.0
audit-deps = { cmd = "pip-audit --local -s osv --ignore-vuln=PYSEC-2025-61" }
The comment is added to save future developers effort in confirming the issue. At a later date, the team should periodically remove the suppression and confirm the issue persists or remove the suppression permanently.
Pixi is the single tool used to manage environments, dependencies, packaging, and task execution for this project.
All metadata is centralized in pyproject.toml
, eliminating the need for environment.yml
or meta.yaml
.
- Install
pixi
by runningcurl -fsSL https://pixi.sh/install.sh | bash
(or following the instruction on the official website) - Run
pixi install
to create the virtual environments. By default,pixi
creates a virtual environment in the.pixi
directory at the root of the repository. - Run
pixi shell
to start a shell with an activate environment, and typeexit
to exit the shell.
Adjust the tasks in pyproject.toml
to match your project's needs.
Detailed instructions on adding tasks can be found in the official documentation.
You can use pixi task list
to see available tasks and their descriptions.
$> pixi task list
Tasks that can run on this machine:
-----------------------------------
Task Description
audit-deps Audit the package dependencies for vulnerabilities
build-docs Build documentation
conda-build Build the conda package
pypi-build Build the package for PyPI
test Run the test suite
Use pixi run <task-name>
to run a specific task (note: if the selected task has dependencies, they will be run first).
You don't need to run pixi shell
to run tasks, as pixi run
will automatically activate the environment for you.
Install direnv
and create a file .envrc
in the project root directory with the following content:
watch_file pixi.lock
eval "$(pixi shell-hook)"
unset PS1
- The line watch_file pixi.lock directs direnv to re-evaluate the environment whenever the file
pixi.lock
changes. - The line
unset PS1
prevents direnv from reporting on a nagging, albeit harmless, error message.
Then in the terminal, run direnv allow
.
Now direnv activates the environment when you enter the project directory,
and deactivates it when you leave the directory.
On SNS Analysis systems, the pixi run conda-build
task will fail due to sqlite3
file locking issue.
This is most likely due to the user directory being a shared mount,
which interferes with pixi
and conda
environment locking.