A new minor version indicates new features, without breaking changes
A new patch version indicates a small change, e.g. a bug fix
Each of the numbers can be higher than 9, e.g. 1.0.0 is more recent than 0.24.12
Version 1.0
A version number of 1.0 indicates that the package is ready for production
The API is stable, and breaking changes will only be introduced in new major versions
The package is well tested, and the documentation is complete
Start with version 0.1.0 and increase the version number as you add features
Breaking changes
What is a breaking change?
Removing a function
Changing the name of a function
Changing the signature of a function (arguments, types, return value)
Try to avoid breaking changes, if possible, but if you do, increase the major version number!
Installing specific versions
pip install my_library will install the latest version
pip install my_library==1.0.0 will install version 1.0.0
pip install my_library>=1.0.0 will install version 1.0.0 or higher
Pre-release versions
Versions that are not ready for production
Indicated by a suffix, e.g. 1.0.0rc1
Will not be installed by default
Can be installed with pip install my_library==1.0.0rc1
Listed on PyPI, but not on the search page
Understanding Software Licenses
A software license is a legal agreement that grants users certain rights and imposes restrictions on the use, modification, and distribution of a software package.
Specifying a license for your Python package is crucial, as it determines how others can legally use and interact with your code.
If you don’t specify a license, your package is effectively “all rights reserved,” making it legally unusable by others.
Check that your dependencies have a license!
Common Open-Source License Types
MIT License: Highly permissive, allows commercial use, modification, and distribution with minimal restrictions.
BSD-3 Clause License: Similar to MIT, but includes a clause prohibiting use of the name for endorsement.
Apache License 2.0: Includes a patent grant and is compatible with the GPL family of licenses.
GNU GPL Family (GPL, LGPL, AGPL): Copyleft licenses that require derivative works to be open-source and distributed under the same terms.
Many popular Python packages, such as scikit-learn, use licenses like BSD-3 or Apache 2.0.
Licenses for internal packages
For internal packages that will not be distributed outside your organization:
You can use a simple copyright notice instead of a full license
Example copyright notice:
# Copyright (c) [COMPANY NAME]
# All rights reserved.
The copyright notice can be placed in the header of each Python file
Avoids the need to maintain a separate license file
Choosing and Implementing a License
When using open-source dependencies in internal packages:
Check the licenses of your dependencies and ensure compatibility
Document the licenses of all third-party components in your project
By following these practices, you can effectively manage the licensing for both your internal and publicly distributed Python packages.
Dependencies
Application
A program that is run by a user
command line tool
script
web application
Pin versions to ensure reproducibility, e.g. numpy==1.11.0
Library
A program that is used by another program
Python package
Low level library (C, Fortran, Rust, …)
Make the requirements as loose as possible, e.g. numpy>=1.11.0
pyproject.toml
[build-system]requires=["hatchling"]build-backend="hatchling.build"[project]name="my_library"version="0.0.1"dependencies=["numpy"]authors=[{ name="First Last", email="initials@dhigroup.com" },]description="Useful library"readme="README.md"requires-python=">=3.12"classifiers=["Programming Language :: Python :: 3","License :: OSI Approved :: MIT License","Development Status :: 2 - Pre-Alpha","Operating System :: OS Independent","Intended Audience :: Science/Research","Topic :: Scientific/Engineering",][dependency-groups]dev=["pytest","ruff","mypy","mkdocs","mkdocstrings[python]","mkdocs-material"]test=["pytest"][project.urls]"Homepage"="https://github.com/DHI/my_library""Bug Tracker"="https://github.com/DHI/my_library/issues"
Classifiers
classifiers=["Programming Language :: Python :: 3","License :: OSI Approved :: MIT License","Development Status :: 2 - Pre-Alpha","Operating System :: OS Independent","Intended Audience :: Science/Research","Topic :: Scientific/Engineering",]
Classifiers are used to categorize your package
Less relevant for internal packages
Operating system (Windows, Linux, MacOS)
Development status (Alpha, Beta, Production/Stable)
Packaging non-Python files
Including non-Python files can be useful for e.g. machine learning models.
If you use hatchling, you can include non-Python files in your package.
hatchling uses .gitignore to determine which files to include.
GitHub secrets
Store sensitive information, e.g. passwords, in your repository.
Secrets are encrypted, and only visible to you and GitHub Actions.
Add secrets in the repository settings.
To use secrets as environment variables in GitHub Actions, add them to the env section of the workflow: