-
Notifications
You must be signed in to change notification settings - Fork 62
Version specification in main text of tutorials/pyproject-toml.md
#191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
a832d9b
10fb76a
2b1cd51
c59600b
15f6040
9ce4bc1
972dbf2
ba9f79c
713ac6a
20f4bef
6bb0f9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -255,8 +255,11 @@ license = {file = 'LICENSE'} | |
``` | ||
### Step 3: Add requires-python to your [project] table | ||
|
||
Finally, add the `requires-python` field to your `pyproject.toml` `[project]` table. The `requires-python` field, helps pip understand the lowest version of Python that you package supports when it's installed. It is thus a single value. | ||
|
||
Add the `requires-python` field to your `pyproject.toml` `[project]` table. | ||
The `requires-python` field, helps pip understand which versions of Python that you package supports when it's installed. | ||
It is thus a single value. | ||
sneakers-the-rat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
`requires-python` supports the dependency specification syntax discussed in the next section - typically this will be | ||
sneakers-the-rat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
a lower bound specifying the oldest version of python that can run your package, but you may also need to specify an upper bound in some more advanced cases. | ||
sneakers-the-rat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
{emphasize-lines="13"} | ||
```toml | ||
|
@@ -284,8 +287,40 @@ The `dependencies =` section contains a list (or array in the toml language) of | |
[build-system] # <- this is a table | ||
requires = ["hatchling"] # this is an array (or list) of requirements | ||
``` | ||
|
||
dependencies are added in an array (similar to a Python list) structure. | ||
|
||
```toml | ||
dependencies = ["numpy", "requests", "pandas", "pydantic"] | ||
``` | ||
|
||
Dependencies can, and usually should come with a **version specifier.** | ||
sneakers-the-rat marked this conversation as resolved.
Show resolved
Hide resolved
lwasser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
A plain dependency says that your package can work with any version of that dependent package. | ||
sneakers-the-rat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Code changes over time, bugs are fixed, APIs change, and so it's good to be clear about which version of the dependency you wrote your code to be compatible with - a package you wrote this year probably isn't compatible with numpy v0.0.1! | ||
willingc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
[Learn more about various ways to specify ranges of package versions here.](https://packaging.python.org/en/latest/specifications/version-specifiers/#id5) | ||
|
||
The most common version specifier is a **lower bound,** allowing any version higher than the specified version. | ||
Ideally you should set this to the lowest version that is still compatible with your package, but in practice for new packages this is often set at the version that was current at the time the package was written. | ||
willingc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Lower bounds look like this: | ||
|
||
```toml | ||
dependencies = [ "numpy>=1.0" ] | ||
``` | ||
|
||
You can combine specifiers with commas, and use different kinds of specifiers for each package in your `dependencies` section: | ||
sneakers-the-rat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```toml | ||
dependencies = [ | ||
"numpy>=1.0", # Greater than or equal to 1.0 | ||
"requests==10.1", # Exactly 10.1 | ||
"pandas", # Any version | ||
"pydantic>=1.7,<2" # Greater than or equal to 1.7, but less than 2 | ||
] | ||
``` | ||
|
||
Your `pyproject.toml` file will now look like this: | ||
|
||
{emphasize-lines="15"} | ||
```toml | ||
|
@@ -303,31 +338,30 @@ readme = "README.md" | |
license = {file = 'LICENSE'} | ||
requires-python = ">=3.10" | ||
|
||
dependencies = ["numpy", "requests", "pandas", "pydantic"] | ||
dependencies = ["numpy>=1.0", "requests==10.1", "pandas", "pydantic>=1.7,<2"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sneakers-the-rat one thing i think users will get stuck on here is how do they know what minimum version of a tool a package supports? i'm not sure how we'd explain that. it's not trivial because normally if you are new to software dev you are just installing tools and you won't do any pinning or lower or upper bound entries at all (unless you use poetry which has defaults). So how would i know (as a scientist who is a beginner to creating a package) that my tool can't support numpy < 1.0 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so this comment is really about adding some direction to a scientist on how to figure this out. rather than telling them to use a lower bounds with out any guidance as to how to do it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I typically set to the lower bound to the version that I create the package with. Described in another comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I initially had that in here but took it out bc i didn't want to be too verbose, but if this is a sticking point then yes :). poetry at least does this automatically with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sneakers-the-rat I think if we choose the greater than current numpy version and make the comment: "Greater than or equal to the current version" that might clarify for @lwasser's concern. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes this would absolutely clarify my concern. i think this is important to add but also guiding a user through how to pick the minimum version would be great. Currently using hatch, it does not support this feature (yet i think anyway) but i'm pretty sure ofek plans to add something like this? or that locking and deps are in the future of hatch's tooling. if you could add this clarification that would be great. @sneakers-the-rat |
||
``` | ||
|
||
:::{admonition} Pin dependencies with caution | ||
Pinning dependencies refers to specifying a specific version of a dependency like this `numpy == 1.0`. In some specific cases, you may chose to pin a package version for a specific package dependency. | ||
"Pinning" dependencies refers to specifying a specific version of a dependency like this: | ||
sneakers-the-rat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Declaring lower bounds involves ensuring that a user has at least a specific version (or greater) of a package installed. This is important as often your package is not backwards compatible with an older version of a tool - for example a version of Pandas that was released 5 years ago. | ||
|
||
You can declare a lower bound using syntax like this: | ||
|
||
`ruamel-yaml>=0.17.21` | ||
|
||
[Learn more about various ways to specify ranges of package versions here.](https://packaging.python.org/en/latest/specifications/version-specifiers/#id5) | ||
|
||
Note that unless you are building an application, you want to be cautious about pinning dependencies to precise versions. For example: | ||
|
||
`numpy == 1.0.2` | ||
`numpy == 1.0`. | ||
|
||
Unless you are building an application, you want to be cautious about pinning dependencies to precise versions. | ||
willingc marked this conversation as resolved.
Show resolved
Hide resolved
sneakers-the-rat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
This is because | ||
users will be installing your package into various environments. | ||
A dependency pinned to a single specific version can make | ||
resolving a Python environment more challenging. As such only | ||
pin dependencies to a specific version if you absolutely need to | ||
do so. | ||
|
||
Similarly, you should be cautious when specifying an upper bound on a package. | ||
These two specifications are equivalent: | ||
|
||
``` | ||
pydantic>=1.10,<2 | ||
pydantic^1.10 | ||
``` | ||
|
||
One build tool that you should be aware of that pins dependencies to an upper bound by default is Poetry. [Read more about how to safely add dependencies with Poetry, here.](../package-structure-code/python-package-build-tools.html#challenges-with-poetry) | ||
::: | ||
|
||
|
@@ -370,7 +404,7 @@ readme = "README.md" | |
license = {file = 'LICENSE'} | ||
requires-python = ">=3.10" | ||
|
||
dependencies = ["numpy", "requests", "pandas", "pydantic"] | ||
dependencies = ["numpy>=1.0", "requests==10.1", "pandas", "pydantic>=1.7,<2"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes so here - i know pydantic well at this point. below 2.0 makes sense. but why did you pick 1.7 as the lower bound? and why doesn't pandas have any bounds? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just random numbers to illustrate the version syntax :) - showing you can do exact pins, lower bounds, ranges, or unspecified - let me add some annotations to make that explicit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. awesome. yes that clarification would be great. for instance the pydantic <2 makes a ton of sense |
||
|
||
classifiers = [ | ||
"Development Status :: 4 - Beta", | ||
|
@@ -410,7 +444,7 @@ readme = "README.md" | |
license = {file = 'LICENSE'} | ||
requires-python = ">=3.10" | ||
|
||
dependencies = ["ruamel-yaml>=0.17.21", "requests", "python-dotenv", "pydantic"] | ||
dependencies = ["numpy>=1.0", "requests==10.1", "pandas", "pydantic>=1.7,<2"] | ||
|
||
classifiers = [ | ||
"Development Status :: 4 - Beta", | ||
|
@@ -452,7 +486,7 @@ readme = "README.md" | |
license = {file = 'LICENSE'} | ||
requires-python = ">=3.10" | ||
|
||
dependencies = ["ruamel-yaml>=0.17.21", "requests", "python-dotenv", "pydantic"] | ||
dependencies = ["numpy>=1.0", "requests==10.1", "pandas", "pydantic>=1.7,<2"] | ||
|
||
classifiers = [ | ||
"Development Status :: 4 - Beta", | ||
|
@@ -525,11 +559,11 @@ classifiers = [ | |
] | ||
|
||
|
||
dependencies = ["xarray", "requests"] | ||
dependencies = ["numpy>=1.0", "requests==10.1", "pandas", "pydantic>=1.7,<2"] | ||
# This is the metadata that pip reads to understand what versions your package supports | ||
requires-python = ">=3.10" | ||
readme = "README.md" | ||
license = { FILE = LICENSE } | ||
license = { file = "LICENSE" } | ||
|
||
# Add urls for your home page, issue tracker and source code | ||
[project.urls] # Optional | ||
|
Uh oh!
There was an error while loading. Please reload this page.