this feels like surprising behavior, and i don't u...
# pex
a
this feels like surprising behavior, and i don't understand why this command would fail to resolve a distribution with what seems like matching requirements. is it a known issue that
>=3.6
appears to not match
==3.6.4
? i expect this is an issue with the pip resolver since we don't really touch those requirements?
Copy code
> pex --interpreter-constraint='CPython==3.6.4' --interpreter-constraint='CPython>=3.6,<4' tensorflow==1.14.0
Could not satisfy all requirements for tensorflow==1.14.0:
    tensorflow==1.14.0
> pex --interpreter-constraint='CPython==3.6.4' tensorflow==1.14.0
Python 3.6.4 (default, Jan 23 2018, 10:58:43)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
h
what’s the output of
pex --interpreter-constraint='CPython>=3.6,<4' tensorflow==1.14.0
What Pex version?
a
1.6.7, running that command now
...........
Copy code
> pex --interpreter-constraint='CPython>=3.6,<4' tensorflow==1.14.0
Could not satisfy all requirements for tensorflow==1.14.0:
    tensorflow==1.14.0
thank you for helping me understand this
i have no clue why that's not working and it deserves maybe a little more thought but fine for now
e
Respectfully, pex 1.6.x doesn't deserve much further thought. If you can re-run with pex 2.1.0 and it works, great. If not, you'll likely get a much clearer failure message.
👍 1
That said, please remember to use debug mode when debugging:
Copy code
$ ~/Downloads/pex-1.6.12.pex -vvvvvvvvv --interpreter-constraint='CPython==3.6.4' --interpreter-constraint='CPython>=3.6,<4' tensorflow==1.14.0
pex: creating PythonIdentity from id string: pp pypy_73 273 2 7 13
pex: creating PythonIdentity from id string: cp cp27mu 27 2 7 17
pex: creating PythonIdentity from id string: cp cp34m 34 3 4 9
pex: creating PythonIdentity from id string: cp cp36m 36 3 6 10
pex: creating PythonIdentity from id string: cp cp35m 35 3 5 9
pex: creating PythonIdentity from id string: cp cp34m 34 3 4 9
pex: creating PythonIdentity from id string: cp cp37m 37 3 7 6
pex: creating PythonIdentity from id string: cp cp37m 37 3 7 6
pex: creating PythonIdentity from id string: cp cp35m 35 3 5 9
pex: creating PythonIdentity from id string: cp cp36m 36 3 6 10
pex: Constraints on interpreters: ['CPython==3.6.4', 'CPython>=3.6,<4'], Matching Interpreter: /usr/bin/python3.8
pex: Constraints on interpreters: ['CPython==3.6.4', 'CPython>=3.6,<4'], Matching Interpreter: /usr/bin/python3.6
pex: Constraints on interpreters: ['CPython==3.6.4', 'CPython>=3.6,<4'], Matching Interpreter: /usr/bin/python3.7m
pex: Constructed RequestsContext context <pex.http.RequestsContext object at 0x7f963d7afeb0>
pex: 
Modifying given platform of 'current':
Using the current platform of Platform(platform='linux_x86_64', impl='cp', version='38', abi='cp38')
Under current interpreter PythonInterpreter('/usr/bin/python3.8', PythonIdentity('cp', 'cp38', '38', 3, 8, 1))

To match given interpreter PythonInterpreter('/usr/bin/python3.8', PythonIdentity('cp', 'cp38', '38', 3, 8, 1)).

Calculated platform: Platform(platform='linux_x86_64', impl='cp', version='38', abi='cp38')
pex: R: tags for Platform(platform='linux_x86_64', impl='cp', version='38', abi='cp38') x PythonInterpreter('/usr/bin/python3.8', PythonIdentity('cp', 'cp38', '38', 3, 8, 1)) -> [('cp38', 'cp38', 'linux_x86_64'), ('cp38', 'cp38', 'manylinux1_x86_64'), ('cp38', 'abi3', 'linux_x86_64'), ('cp38', 'abi3', 'manylinux1_x86_64'), ('cp38', 'none', 'linux_x86_64'), ('cp38', 'none', 'manylinux1_x86_64'), ('cp37', 'abi3', 'linux_x86_64'), ('cp37', 'abi3', 'manylinux1_x86_64'), ('cp36', 'abi3', 'linux_x86_64'), ('cp36', 'abi3', 'manylinux1_x86_64'), ('cp35', 'abi3', 'linux_x86_64'), ('cp35', 'abi3', 'manylinux1_x86_64'), ('cp34', 'abi3', 'linux_x86_64'), ('cp34', 'abi3', 'manylinux1_x86_64'), ('cp33', 'abi3', 'linux_x86_64'), ('cp33', 'abi3', 'manylinux1_x86_64'), ('cp32', 'abi3', 'linux_x86_64'), ('cp32', 'abi3', 'manylinux1_x86_64'), ('py3', 'none', 'linux_x86_64'), ('py3', 'none', 'manylinux1_x86_64'), ('cp38', 'none', 'any'), ('cp3', 'none', 'any'), ('py38', 'none', 'any'), ('py3', 'none', 'any'), ('py37', 'none', 'any'), ('py36', 'none', 'any'), ('py35', 'none', 'any'), ('py34', 'none', 'any'), ('py33', 'none', 'any'), ('py32', 'none', 'any'), ('py31', 'none', 'any'), ('py30', 'none', 'any')]
pex: Constructed RequestsContext context <pex.http.RequestsContext object at 0x7f963d7b04c0>
pex: crawling link i=0 link=Link('file:///home/jsirois/.pex/build') follow_links=False
pex: crawling link i=0 link=Link('<https://pypi.org/simple/tensorflow/>') follow_links=False
Could not satisfy all requirements for tensorflow==1.14.0:
    tensorflow==1.14.0
Note since you pass 2 seperate --interpreter-constraint, they are OR'd (as per help docs), and in this case the second constraint won, ie: >=3.6,<4 and that picked python 3.8 on my machine. Tensorflow 1.14.0 is wheel only and definitely doesn;t have python 3.8 wheels: https://pypi.org/project/tensorflow/1.14.0/#files
So the failure - in my case above - makes sense.
a
ah! i see how the PEX_VERBOSE output would have helped to solve this. thank you!
i didn’t realize i was ORing the constraints before resolution
e
For bystanders, what was the solution. Was your example also picking python3.8?
☝️ 1
a
i suppose the comma
CPython>=3.6,<4,==3.6.4
might have done the appropriate ANDing
yes it was picking 3.8
e
the , does do AND as it does generally in python requirements
👍 2
a
yes, was just checking
e
But, that said, range && pin always just is pin
So there would be no point
a
oh yes. i’m thinking about how to merge two separate requirements into one automatically (there’s no particular reason for this, because for ipex we only need the == constraint for the interpreter we use at build time). i can’t see a use case for this right now but it seems possible to generate a requirement string with the appropriate logic
e
a
oh yes! i have some very nice logic to split python targets by interpreter (in a PR i should close now) which uses specifiers, although i believe it becomes utterly useless for the pants v2 engine which covers that already