Defining a Static Version¶
pyproject.toml
has certain fields that are required, which are described in the Python Packaging Guide:
[project]
name = "arrow-to-knee" # required!
version = "1.0.0" # required!
As a Build front end, Hatch provides a nice CLI to find out the current package version:
$ hatch version
1.0.0
You can also use this sub-command to set the version:
$ hatch version 2.0.0
Old: 1.0.0
New: 2.0.0
By default, this will update the pyproject.toml
:
[project]
name = "arrow-to-knee" # required!
version = "2.0.0" # required!
What About the __version__
Name?¶
Some people prefer to define their version in a __version__
global variable in their Import package. The __version__
variable is a convention (not a standard) that some packages use for exposing this infmormation to other users of their package.
__version__ = "1.0.0"
Setting __verion__
lets you use the version number in your code, e.g. to print it out:
def show_package_info():
print(f"This package has version {__version__}")
It’s possible to get the installed version another way, via the importlib.metadata
package that we saw earlier:
import importlib.metadata
importlib.metadata.version("arrow-to-knee")
This is the standard way to get at installed Distribution package metadata, but it can be “slow” as it has to perform file-system operations.
How Do I Use __version__
with hatchling
?¶
First, set the version
to be dynamic and remove the version
field:
[project]
dynamic = ["version"]
# version = "1.0.0"
Then tell hatchling
about the version source:
[tool.hatch.version]
source = "regex"
path = "src/arrow_to_knee/__init__.py"
Now, we can use te hatch version
command once again to set the version, and Hatch will update the __init__.py
file instead of pyproject.toml
.
How Do I Build a Dynamic README?¶
Many projects also use dynamic README files. The intention behind this is often one of reducing duplication whilst also distributing different README files for different platforms. For example, the kinds of information that package authors want to show to users on PyPI may differ from those that they want contributors to the GitHub repository to say (such as the inclusion/removal of Markdown badges). For example the awkward-array project uses this to hide the code-contributing guidelines from the PyPI users, and change out the logo.
To build a dynamic readme, first, add hatch-fancy-pypi-readme
to your [build-system]
table:
[build-system]
requires = ["hatchling", "hatch-fancy-pypi-readme"]
build-backend = "hatchling.build"
This is a particular hatchling
plugin that knows how to build a README, and we need to define it here so that the package manager installs the plugin before trying to build your package. Then tell hatchling
about the dynamic readme and remove the readme
field:
[project]
dynamic = ["version", "readme"]
This will signal to build frontends that they will need to ask hatchling
to compute the readme (and version), if they want to read it. Next, configure the fancy-pypi-readme
tool with the knowledge that our README is Markdown:
[tool.hatch.metadata.hooks.fancy-pypi-readme]
content-type = "text/markdown"
Finally, define your readme fragments
. These individual parts are concatenated together to form a contiguous block of text. Here, we’re interleaving a fragment taken from the README.md
file (between some BEGIN
and END
markers that we’re pre-inserted into that file), a block of raw text, and another fragment from README.md
. You can see how this might be quite powerful!
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
path = "README.md"
start-after = "<!-- BEGIN README 1 -->"
end-before = "<!-- END README 1 -->"
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
text = "This is a readme\n"
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
path = "README.md"
start-after = "<!-- BEGIN README 2 -->"
end-before = "<!-- END README 2 -->"