2015-04-07 67 views
6

目前Django Project支持1.4,1.7和1.8。在我的setup.py我想反映這些版本是受支持的。在setuptools/pip中排除某些依賴版本範圍

install_requires=['Django>=1.4.2,<1.8.99,!=1.5,!=1.6'] 

但是,這仍然允許1.5.x和1.6.x版本。我如何排除一個完整的範圍?

Setuptools lists以下有效需求爲例:

PickyThing<1.6,>1.9,!=1.9.6,<2.0a0,==2.4c1 

然而,這並不與PIP工作(至少應該匹配的1.4.x/1.5.x版):

無匹配找到PickyThing分配!= 1.9.6,< 1.6,< 2.0a0,== 2.4c1,> 1.9

用示例更新
例如;我只想包括currently supported versions of Django。這將是1.4.x,1.7.x和1.8.x.所以我會寫;

#setup.py 
install_requires=['Django>=1.4.2,<1.4.99,>=1.7,<1.8.99'] 

但是,如果我在此項目上運行pip install -e .,則會失敗;

Collecting Django<1.4.99,<1.8.99,>=1.4.2,>=1.7 (from ...) 
Could not find a version that satisfies the requirement Django<1.4.99,<1.8.99,>=1.4.2,>=1.7 (from django-two-factor-auth==1.2.0) (from versions: 1.1.3, 1.1.4, 1.2, 1.2.1, 1.2.2, 1.2.3, 1.2.4, 1.2.5, 1.2.6, 1.2.7, 1.3, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.3.7, 1.4, 1.4.1, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.4.8, 1.4.9, 1.4.10, 1.4.11, 1.4.12, 1.4.13, 1.4.14, 1.4.15, 1.4.16, 1.4.17, 1.4.18, 1.4.19, 1.4.20, 1.5, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.5.6, 1.5.7, 1.5.8, 1.5.9, 1.5.10, 1.5.11, 1.5.12, 1.6, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5, 1.6.6, 1.6.7, 1.6.8, 1.6.9, 1.6.10, 1.6.11, 1.7, 1.7.1, 1.7.2, 1.7.3, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.8a1, 1.8b1, 1.8b2, 1.8rc1, 1.8, 1.8.1) 
No matching distribution found for Django<1.4.99,<1.8.99,>=1.4.2,>=1.7 (from ...) 

顯而易見的是,版本號1.4.20不能滿足>=1.7和1.8.1不能滿足<1.4.99。然而,Setuptools的文檔(見上文)確實表明應該可以採用這些方法。但是,這對我來說並不明顯。

+0

這個錯誤發生在做什麼的時候? – skyline75489

+0

@ skyline75489看到我的更新。 – bouke

+0

你正在使用哪個pip版本? – skyline75489

回答

1

我讀過一些相關的代碼pkg_resources。我認爲文檔here不準確。不僅pip找不到正確的軟件包版本,python setup.py install,實際上使用setuptools,也失敗。

一些相關的代碼:

PIP/_vendor /包裝/ specifiers.py

# If we have any specifiers, then we want to wrap our iterable in the 
# filter method for each one, this will act as a logical AND amongst 
# each specifier. 
if self._specs: 
    for spec in self._specs: 
     iterable = spec.filter(iterable, prereleases=prereleases) 
    return iterable 

你可以看到,在評論中,筆者強調,這將導致AND之中每個說明符,而不是OR。所以如果你這樣做:

PickyThing<1.6,>1.9,!=1.9.6,<2.0a0,==2.4c1 

你什麼也得不到!

我試着用下面這段代碼:

import pkg_resources 

a = ['1.4', '1.8', '1.9.2'] 
d = pkg_resources.Requirement.parse('PickyThing<1.6,>1.9,!=1.9.6') 
r = d.specifier.filter(a) 

print(list(r)) # Nothing, just an empty list [] 

您可能需要一個bug提交到pip這樣他們就可以解決這個問題。

+0

感謝您的調查,我將獎賞賞金,一旦可用。我已將[錯誤報告](https://github.com/pypa/pip/issues/2744)提交給pip。 – bouke

2

您可以使用Django>=1.4.2,<1.9,!=1.5.*,!=1.6.*

這裏面PEP440定義。

您可以使用packaging模塊測試此行爲,該模塊在最新版本的setuptools和pip內部進行銷售。

In [1]: from packaging import specifiers 

In [2]: sp=specifiers.SpecifierSet(">=1.4.2,<1.9,!=1.5.*,!=1.6.*") 

In [3]: sp.contains("1.4.2") 
Out[3]: True 

In [4]: sp.contains("1.6.4") 
Out[4]: False 

In [5]: sp.contains("1.8.2") 
Out[5]: True 
+0

這看起來很不錯,謝謝! – bouke