Skip to content

Commit 679da01

Browse files
docs: add guidance on dependency version range (#586)
* docs: add guidance on dependency version range * docs: fix vale warnings * Update doc/source/how-to/packaging.rst Co-authored-by: Roberto Pastor Muela <[email protected]> * refactor: update following reviews * docs: fix vale warning * docs: fix typo in code-block * docs: fix code block rendering --------- Co-authored-by: Roberto Pastor Muela <[email protected]>
1 parent fe9ed8e commit 679da01

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

doc/source/how-to/packaging.rst

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,100 @@ Examples of PyAnsys projects that have these optional dependencies are:
400400
- `PyAnsys Geometry targets <https://github.com/ansys/pyansys-geometry/blob/e6d8210f9d79718d607a2f4b2e8ead33babcbfca/pyproject.toml#L44-L58>`_
401401
- `PyACP targets <https://github.com/ansys/pyacp/blob/f4d8c1779cd451b1fc8ef649cc3b2cd5799ff11a/pyproject.toml#L89-L110>`_
402402

403+
Dependency version range
404+
------------------------
405+
406+
.. note::
407+
408+
This guidance applies only to PyAnsys *library* projects. For projects
409+
which deliver an *application* or *dedicated workflow*, it is
410+
recommended to fully pinning all (direct and transitive) dependencies.
411+
412+
When specifying dependencies in a project, it is generally recommended to avoid
413+
setting upper version limits unless it is absolutely necessary. The reason for
414+
that is because arbitrarily restricting a dependency to be lower than a
415+
certain version (for example `numpy<2.0`) can prevent your project from working
416+
with newer and perfectly compatible versions, and often causes more problems
417+
than it solves. Such restrictions limit forward compatibility, block users from
418+
upgrading dependencies, and increase the risk of version conflicts.
419+
420+
This issue is even more critical in the context of the PyAnsys `metapackage`_
421+
which install many PyAnsys projects. In this setup, having strict upper bounds
422+
on versions can easily result in unsatisfiable dependency constraints across
423+
the ecosystem. For instance, if a package declares a dependency on `numpy<2.0`
424+
despite being compatible with later versions, and another package requires
425+
`numpy>=2.0.0` to leverage a new feature, it becomes impossible to install
426+
both packages simultaneously. This occurs even though no actual incompatibility
427+
exists between them, and it can lead to frustration for users and maintainers
428+
as it prevents otherwise compatible packages from being used together seamlessly.
429+
430+
It is better to define only a minimum version (`>=`) and rely on Continuous
431+
Integration (CI) to detect real breakages as dependencies evolve. If a future
432+
version does introduce a breaking change, you can then add an upper bound with
433+
a clear explanation. For example:
434+
435+
.. code-block:: toml
436+
437+
[project]
438+
dependencies = [
439+
"numpy<2.0", # breaking changes in Python and C APIs'.
440+
]
441+
442+
Setting a lower bound (`>=`) is considered good practice for multiple reasons.
443+
First, it documents the oldest version of a dependency that your project
444+
explicitly supports. It is often the oldest version that is compatible with
445+
the Python versions you support. For example, if your project supports
446+
Python versions from `3.11` to `3.13`, you need to ensure that all dependencies
447+
are compatible with at least Python `3.11`. This is important for users who may
448+
be using older versions of Python and want to ensure compatibility with your
449+
project. In other cases, the lower bound is related to the version where
450+
certain key features your code relies on were first introduced. For instance,
451+
if your code uses an API or behavior that only appeared in version `1.3`,
452+
setting `>=1.3` communicates both a technical requirement and an implicit
453+
contract to your users and contributors.
454+
455+
This helps avoiding unexpected breakages when someone installs your project
456+
in an environment with older versions of dependencies. Rather than encountering
457+
obscure runtime errors or missing features, the version constraint prevents
458+
your project to be installed. It also helps to maintain clarity for long-term
459+
maintenance and simplifies debugging.
460+
461+
Below is an example of a dependency specification that follows these guidelines:
462+
463+
.. tab-set::
464+
465+
.. tab-item:: flit
466+
467+
.. code-block:: toml
468+
469+
[project]
470+
dependencies = [
471+
"matplotlib>=3.5.2",
472+
"numpy>=1.20.0",
473+
]
474+
475+
.. tab-item:: poetry
476+
477+
.. code-block:: toml
478+
479+
[tool.poetry.dependencies]
480+
matplotlib = ">=3.5.2"
481+
numpy = ">=1.20.0"
482+
483+
.. tab-item:: setuptools
484+
485+
.. code-block:: python
486+
487+
from setuptools import setup
488+
489+
setup(
490+
...,
491+
install_requires=[
492+
"matplotlib >= 3.5.2",
493+
"numpy >= 1.20.0",
494+
],
495+
)
496+
403497
Dependabot
404498
----------
405499

0 commit comments

Comments
 (0)