66

I want to make a package to depend the particular version range e.g. >= 0.5.0, < 0.7.0. Is it possible in install_requires option, and if so how should it be?

minhee
  • 5,688
  • 5
  • 43
  • 81
  • 4
    What have you tried? [The docs](http://peak.telecommunity.com/DevCenter/setuptools#declaring-dependencies) seem to suggest that syntax just like what you have in your question will work. – Blckknght Jul 15 '12 at 18:49

5 Answers5

55

According to the documentation, your syntax should work correctly. The documentation states that:

setuptools and pkg_resources use a common syntax for specifying a project's required dependencies. This syntax consists of a project's PyPI name, optionally followed by a comma-separated list of "extras" in square brackets, optionally followed by a comma-separated list of version specifiers. A version specifier is one of the operators <, >, <=, >=, == or !=, followed by a version identifier.

The documentation gives a simple example like this:

docutils >= 0.3

# comment lines and \ continuations are allowed in requirement strings
BazSpam ==1.1, ==1.2, ==1.3, ==1.4, ==1.5, \
    ==1.6, ==1.7  # and so are line-end comments

To expand upon that, if you want your package to require a version of docutils greater than version 0.3 but less than version 0.5, code like this would work:

docutils >= 0.3, <=0.5

Two additional notes.

  1. The documentation also states that redundant/overlapping dependency specifications will be combined internally, so docutils >= 0.3, >=0.2 would be combined into docutils >= 0.3.
  2. Also, be careful about specifying conflicting version numbers, which "is meaningless and may therefore produce bizarre results." For example, I don't know why you would, but don't use this: docutils >= 0.3, <=0.2 since this is impossible.
Quentin Pradet
  • 4,691
  • 2
  • 29
  • 41
Ricardo Altamirano
  • 14,650
  • 21
  • 72
  • 105
  • 7
    Great answer, but what confuses me is that the comma sometimes means **or** and sometimes **and**: the list of exact version specs clearly says '1.1 or 1.2 or ...' and combining `>= 0.3, >=0.2` to just `>=0.2` only makes sense that way. But `>= 0.3, <=0.5` or your paragraph about contradicting version specs need the comma to signify **and**. – zpea Jul 21 '12 at 22:34
  • 1
    to build on @zpea s question: is there any way to define multiple ranges of versions? e.g `(>=1.0 AND <2) OR (>=2.7 AND <2.9) OR (>=4)` – stefanfoulis Aug 04 '15 at 13:41
  • The docs say that >1, >2 become >1, but it would make more sense to become >2, as you said. Anyone knows why? – Quentin Pradet Jul 18 '17 at 08:33
20

Be wary of involuntary beta tests. Package maintainers sometimes release incompatible, incomplete, or broken a, b, and c releases to general audiences without warning. The next time you run setup.py in a fresh virtualenv, you might pull down one of these poisoned eggs, and suddenly your program will break.

To mitigate this risk, do not use the foo >=0.3, <0.4 style declaration, which has a purely numeric upper bound. <0.4 still admits versions 0.4a0, 0.4a1, 0.4b0, 0.4c3, etc. Instead, use an upper bound like <0.4a0, as in foo >=0.3, <0.4a0, when you write your install_requires.

When setuptools does something unexpected, trying using verlib to model your version comparisons. Verlib is a pretty good fit as long as your versions are normalized and non-contradictory. Here is an example that demonstrates the potentially counter-intuitive ordering of normalized versions:

#!/usr/bin/env python

from verlib import NormalizedVersion as V

assert (V("0.7.9") < V("0.8a0") < V("0.8a1") < V("0.8b0") < V("0.8b1")
    < V("0.8b2") < V("0.8.0") < V("0.8.1a0") < V("0.8.1") < V("0.9")
    < V("1.0a3") < V("1.0b2") < V("1.0b20") < V("1.0c0") < V("1.0")
    < V("1.0.1"))

assert (V("0.7.9") < V("0.8.0a0") < V("0.8.0a1") < V("0.8.0b0")
    < V("0.8.0b1") < V("0.8.0b2") < V("0.8.0") < V("0.8.1a0") < V("0.8.1")
    < V("0.9") < V("1.0a3") < V("1.0b2") < V("1.0b20") < V("1.0c0")
    < V("1.0") < V("1.0.1"))

print "Version comparisons are sane."
Mike B
  • 201
  • 2
  • 3
4

The notation mentioned in OP's question, >= 0.5.0, < 0.7.0, already works.

And, since many (if not most) of the libraries would already use semantic versioning, so by definition you can define your dependency as A>=1,<2, as explained here. And they even implemented an even simpler syntax for it, A~=X.Y, meaning it requires at least release X.Y, but also allows any later release with a matching MAJOR version.

RayLuo
  • 17,257
  • 6
  • 88
  • 73
2

Another way to it is to use wildcards.

This does not apply to >= 0.5.0, < 0.7.0, but in case you decide that all maintenance releases should be supported (e.g. 0.5.0 to 0.5.x), you can use

== 0.5.*

e.g. docutils == 0.3.*

Stefan Papp
  • 2,199
  • 1
  • 28
  • 54
  • This is the only setup tools example I found after several sites which shows setup.py syntax for equals, `==`; I was getting version numbers from my Anaconda requirements file and it uses `=`. I got confused. – xtian Aug 24 '19 at 22:29
2

The answer for OP question including the install_requires would be looks like this:

setuptools.setup(
    ...
    install_requires=['package>=0.5.0,< 0.7.0']
    ...
    )

Other example with extra rejecting certain version based on others answer:

setuptools.setup(
    ...
    install_requires=['package>=1.4.2,<1.9,!=1.5.*,!=1.6.*']
    ...
    )
Muhammad Yasirroni
  • 1,512
  • 12
  • 22