Skip to content
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

Python style checker dependencies not consumable for cross-py2/py3 linting iff building a single-python pex #7158

Closed
stuhood opened this issue Jan 25, 2019 · 22 comments
Labels

Comments

@stuhood
Copy link
Member

stuhood commented Jan 25, 2019

When attempting to use a py2 pants pex (edit: built using build-support/bin/release.sh -p) to lint a py3 target in an external repo at master (technically 0406f0f), the following error occurs:

20:12:57 00:18     [pythonstyle]
20:12:57 00:18       [cache]  
                   No cached artifacts for 2 targets.
                   Invalidated 2 targets.
20:12:57 00:18       [build-checker]
20:12:57 00:18       [pythonstyle]
                     Failed to execute PEX file, missing linux_x86_64-cp-36-cp36m compatible dependencies for:
                     pantsbuild.pants.contrib.python.checks.checker
                     future
                     
FAILURE: 1 Python Style issues found. You may try `./pants fmt <targets>`

At least with regard to the checker wheel, this is likely related to #6450. The future dependency is something else... possibly we just need an update to the latest version?

@stuhood
Copy link
Member Author

stuhood commented Jan 25, 2019

And for the record: this was exposed by the deprecation removal in #7063... apparently we had not actually whitelisted any Py3-only targets, so we weren't actually linting them before.

@jsirois
Copy link
Contributor

jsirois commented Jan 27, 2019

At least with regard to the checker wheel, this is likely related to #6450.

I'm not sure how you concluded that. Does the pants pex contain the python checkstyle plugin or not? Have you run with PEX_VERBOSE=9?

@jsirois
Copy link
Contributor

jsirois commented Jan 27, 2019

If you can add more detail that would be great. I was able to nominally do what you describe as failing with:

./pants binary src/python/pants/bin:pants_local_binary
$ head -1 dist/pants_local_binary.pex 
#!/usr/bin/env python2.7

And:

$ git diff --cached
diff --git a/contrib/python/examples/src/python/three/BUILD b/contrib/python/examples/src/python/three/BUILD
new file mode 100644
index 000000000..b801e5d3a
--- /dev/null
+++ b/contrib/python/examples/src/python/three/BUILD
@@ -0,0 +1,3 @@
+python_library(
+  compatibility='>=3.4,<4',
+)
diff --git a/contrib/python/examples/src/python/three/lint.py b/contrib/python/examples/src/python/three/lint.py
new file mode 100644
index 000000000..d2f799eac
--- /dev/null
+++ b/contrib/python/examples/src/python/three/lint.py
@@ -0,0 +1,5 @@
+def func1():
+  pass
+
+def func2():
+  pass

And then:

$ ./dist/pants_local_binary.pex lint contrib/python/examples/src/python/three

18:39:13 00:00 [main]
               See a report at: http://localhost:42959/run/pants_run_2019_01_26_18_39_14_817_242f29321e6d442bbb741f7a31855ae3
18:39:14 00:01   [setup]
18:39:14 00:01     [parse]
               Executing tasks in goals: bootstrap -> imports -> unpack-jars -> deferred-sources -> gen -> native-compile -> jvm-platform-validate -> resolve -> lint
18:39:15 00:02   [bootstrap]
18:39:15 00:02     [substitute-aliased-targets]
18:39:15 00:02     [jar-dependency-management]
18:39:15 00:02     [bootstrap-jvm-tools]
18:39:15 00:02     [provide-tools-jar]
18:39:15 00:02   [imports]
18:39:15 00:02     [ivy-imports]
18:39:15 00:02   [unpack-jars]
18:39:15 00:02     [unpack-jars]
18:39:15 00:02   [deferred-sources]
18:39:15 00:02     [deferred-sources]
18:39:15 00:02   [gen]
18:39:15 00:02     [antlr-java]
18:39:15 00:02     [antlr-py]
18:39:15 00:02     [jaxb]
18:39:15 00:02     [protoc]
18:39:15 00:02     [ragel]
18:39:15 00:02     [thrift-java]
18:39:15 00:02     [thrift-py]
18:39:15 00:02     [grpcio-prep]
18:39:15 00:02     [grpcio-run]
18:39:15 00:02     [wire]
18:39:15 00:02     [avro-java]
18:39:15 00:02     [go-thrift]
18:39:15 00:02     [go-protobuf]
18:39:15 00:02     [jax-ws]
18:39:15 00:02     [scrooge]
18:39:15 00:02     [thrifty]
18:39:15 00:02   [native-compile]
18:39:15 00:02     [conan-prep]
18:39:15 00:02     [native-third-party-fetch]
18:39:15 00:02     [c-for-ctypes]
18:39:15 00:02     [cpp-for-ctypes]
18:39:15 00:02   [jvm-platform-validate]
18:39:15 00:02     [jvm-platform-validate]
18:39:15 00:02   [resolve]
18:39:15 00:02     [ivy]
18:39:15 00:02     [coursier]
18:39:15 00:02     [go]
18:39:15 00:02     [scala-js-compile]
18:39:15 00:02     [scala-js-link]
18:39:15 00:02     [node]
18:39:15 00:02   [lint]
18:39:15 00:02     [scalafix]
                   Skipping scalafix
18:39:15 00:02     [scalafmt]
                   Skipping scalafmt
18:39:15 00:02     [scalastyle]
18:39:15 00:02     [checkstyle]
18:39:15 00:02     [jvm-dep-check]
18:39:15 00:02     [go]
18:39:15 00:02     [google-java-format]
                   Skipping google-java-format
18:39:15 00:02     [javascriptstyle]
18:39:15 00:02     [python-eval]
                   Skipping python-eval
18:39:15 00:02     [pythonstyle]
                   Invalidated 1 target.
18:39:15 00:02       [pythonstyle]
                     
                     T302:ERROR   contrib/python/examples/src/python/three/lint.py:004 Expected 2 blank lines, found 1
                          |def func2():
                     
                     
FAILURE: 1 Python Style issues found. You may try `./pants fmt <targets>`


               Waiting for background workers to finish.
18:39:16 00:03   [complete]
               FAILURE

The ./dist/pants_local_binary.pex server output shows a pex of:

/home/jsirois/dev/pantsbuild/pants/.pants.d/lint/pythonstyle/checker/e0967a4b71b39325e9f5b0ae3b2d68ebbc1f1f74/CPython-3.6.8/.deps/
six-1.12.0-py2.py3-none-any.whl
future-0.16.0-py3-none-any.whl
pyflakes-2.0.0-py2.py3-none-any.whl
pantsbuild.pants.contrib.python.checks.checker-1.14.0.dev2-py2.py3-none-any.whl
pycodestyle-2.4.0-py2.py3-none-any.whl

And this is what I'd expect since the checker wheel is universal.

@jsirois
Copy link
Contributor

jsirois commented Jan 27, 2019

@illicitonion reports what now seems to be a related issue running pants from sources (https://www.pantsbuild.org/howto_develop.html). I likewise don't repro his issue. Do you all include the checker wheel in your wheelhouse?: https://pypi.org/project/pantsbuild.pants.contrib.python.checks.checker/1.14.0.dev2/#files

@stuhood
Copy link
Member Author

stuhood commented Jan 28, 2019

@jsirois : I believe that a critical bit of the repro (have updated the description) is that this is a pants pex built from published wheels using:

function build_pex() {
# Builds a pex from the current UNSTABLE version.
# If $1 == "build", builds a pex just for this platform, from source.
# If $1 == "fetch", fetches the linux and OSX wheels which were built on travis.

This results in a pex containing the following .deps:

Markdown-2.1.1-py2-none-any.whl
Pygments-2.3.1-py2.py3-none-any.whl
ansicolors-1.0.2-py2-none-any.whl
asn1crypto-0.24.0-py2.py3-none-any.whl
asttokens-1.1.13-py2.py3-none-any.whl
certifi-2018.11.29-py2.py3-none-any.whl
cffi-1.11.1-cp27-cp27m-macosx_10_6_intel.whl
cffi-1.11.1-cp27-cp27mu-manylinux1_x86_64.whl
chardet-3.0.4-py2.py3-none-any.whl
configparser-3.5.0-py2-none-any.whl
contextlib2-0.5.5-py2.py3-none-any.whl
cryptography-2.5-cp27-cp27m-macosx_10_6_intel.whl
cryptography-2.5-cp27-cp27mu-manylinux1_x86_64.whl
docutils-0.12-py2-none-any.whl
enum34-1.1.6-py2-none-any.whl
fasteners-0.14.1-py2.py3-none-any.whl
faulthandler-2.6-cp27-cp27m-macosx_10_11_x86_64.whl
faulthandler-2.6-cp27-cp27mu-linux_x86_64.whl
future-0.16.0-py2-none-any.whl
idna-2.8-py2.py3-none-any.whl
ipaddress-1.0.22-py2.py3-none-any.whl
monotonic-1.5-py2.py3-none-any.whl
packaging-16.8-py2.py3-none-any.whl
pantsbuild.pants-1.14.0.dev3+f49243a4-cp27-none-linux_x86_64.whl
pantsbuild.pants-1.14.0.dev3+f49243a4-cp27-none-macosx_10_11_x86_64.whl
pantsbuild.pants.contrib.avro-1.14.0.dev3+f49243a4-py27-none-any.whl
pantsbuild.pants.contrib.confluence-1.14.0.dev3+f49243a4-py27-none-any.whl
pantsbuild.pants.contrib.go-1.14.0.dev3+f49243a4-py27-none-any.whl
pantsbuild.pants.contrib.googlejavaformat-1.14.0.dev3+f49243a4-py27-none-any.whl
pantsbuild.pants.contrib.node-1.14.0.dev3+f49243a4-py27-none-any.whl
pantsbuild.pants.contrib.python.checks-1.14.0.dev3+f49243a4-py27-none-any.whl
pantsbuild.pants.contrib.python.checks.checker-1.14.0.dev3+f49243a4-py2.py3-none-any.whl
pantsbuild.pants.contrib.scalajs-1.14.0.dev3+f49243a4-py27-none-any.whl
pantsbuild.pants.contrib.scrooge-1.14.0.dev3+f49243a4-py27-none-any.whl
pantsbuild.pants.testinfra-1.14.0.dev3+f49243a4-py27-none-any.whl
pathspec-0.5.9-py2-none-any.whl
pex-1.5.3-py2.py3-none-any.whl
ply-3.11-py2.py3-none-any.whl
psutil-5.4.8-cp27-cp27m-macosx_10_11_x86_64.whl
psutil-5.4.8-cp27-cp27mu-linux_x86_64.whl
pyOpenSSL-17.3.0-py2.py3-none-any.whl
py_zipkin-0.17.0-py2.py3-none-any.whl
pycodestyle-2.4.0-py2.py3-none-any.whl
pycparser-2.19-py2.py3-none-any.whl
pyflakes-2.0.0-py2.py3-none-any.whl
pyparsing-2.3.1-py2.py3-none-any.whl
pystache-0.5.3-py2-none-any.whl
pywatchman-1.4.1-cp27-cp27m-macosx_10_11_x86_64.whl
pywatchman-1.4.1-cp27-cp27mu-linux_x86_64.whl
requests-2.21.0-py2.py3-none-any.whl
scandir-1.2-cp27-cp27m-macosx_10_11_x86_64.whl
scandir-1.2-cp27-cp27mu-linux_x86_64.whl
setproctitle-1.1.10-cp27-cp27m-macosx_10_11_x86_64.whl
setproctitle-1.1.10-cp27-cp27mu-linux_x86_64.whl
setuptools-40.4.3-py2.py3-none-any.whl
six-1.12.0-py2.py3-none-any.whl
subprocess32-3.2.7-cp27-cp27m-macosx_10_11_x86_64.whl
subprocess32-3.2.7-cp27-cp27mu-linux_x86_64.whl
thriftpy2-0.4.0-cp27-cp27m-macosx_10_11_x86_64.whl
thriftpy2-0.4.0-cp27-cp27mu-linux_x86_64.whl
twitter.common.collections-0.3.10-py2-none-any.whl
twitter.common.confluence-0.3.10-py2-none-any.whl
twitter.common.dirutil-0.3.10-py2-none-any.whl
twitter.common.lang-0.3.10-py2-none-any.whl
twitter.common.log-0.3.10-py2-none-any.whl
twitter.common.options-0.3.10-py2-none-any.whl
urllib3-1.24.1-py2.py3-none-any.whl
wheel-0.31.1-py2.py3-none-any.whl
www_authenticate-0.9.2-py2-none-any.whl

So the wheel inside the pex is a 2.7 tagged wheel.

@jsirois
Copy link
Contributor

jsirois commented Jan 28, 2019

Thanks - that helps. I'll dig a bit more. NB: the wheel is universal though: pantsbuild.pants.contrib.python.checks.checker-1.14.0.dev3+f49243a4-py2.py3-none-any.whl

@jsirois
Copy link
Contributor

jsirois commented Jan 28, 2019

I can almost guarantee you this is due to future-0.16.0-py2-none-any.whl which is a dep of checker. I can almost certainly guarantee you the pex will need to swtich to multiplatform / multipython instead of just multiplatform.

@stuhood
Copy link
Member Author

stuhood commented Jan 28, 2019

NB: the wheel is universal though: pantsbuild.pants.contrib.python.checks.checker-1.14.0.dev3+f49243a4-py2.py3-none-any.whl

Hah. You're right... good eye.

I can almost certainly guarantee you the pex will need to swtich to multiplatform / multipython instead of just multiplatform.

Is #7159 likely to help? or would we need to have the wheel building shards do something to request a multi-python wheel?

@jsirois jsirois changed the title Python style checker wheel not consumable for cross-py2/py3 linting Python style checker dependencies not consumable for cross-py2/py3 linting iff building a single-python pex Jan 28, 2019
@jsirois
Copy link
Contributor

jsirois commented Jan 28, 2019

Actually - the description is still not right. build-support/bin/release.sh -p does not produce the pex you claim (it has 0 plugins embedded). Exactly what is the command line you use?

@jsirois
Copy link
Contributor

jsirois commented Jan 28, 2019

#7159 would be a bandaid. Fundamentally you are trying to buold a pex that never does tool / plugin resolves yet still works for 2 and 3. If you left the checker out of the pex, it would resolve as 2 or 3 as needed. Since you don't, the pex really needs to be built for both 2 + 3 simultaneously. Anything else works by luck.

@jsirois
Copy link
Contributor

jsirois commented Jan 28, 2019

I'll play around here with building a proper pex to make sure this is even possible today.

@jsirois
Copy link
Contributor

jsirois commented Jan 28, 2019

Yeah - so this is not possible to fix correctly until pantsbuild.pants* are released for python2 and python3. The #7159 bandaid should work, but expect a blowup later.

@stuhood
Copy link
Member Author

stuhood commented Jan 28, 2019

Actually - the description is still not right. build-support/bin/release.sh -p does not produce the pex you claim (it has 0 plugins embedded). Exactly what is the command line you use?

We use -p, but then additionally set:

# A space-separated list of pants packages to include in any pexes that are built: by default,
# only pants core is included.
: ${PANTS_PEX_PACKAGES:="pantsbuild.pants"}
to include relevant plugins.

@jsirois
Copy link
Contributor

jsirois commented Jan 28, 2019

Sigh - understood. I was hoping for an exact command line - it's nice to have exact repro data.

@stuhood
Copy link
Member Author

stuhood commented Jan 28, 2019

Sigh - understood. I was hoping for an exact command line - it's nice to have exact repro data.

The environment looks something like:

export PANTS_PEX_PACKAGES='pantsbuild.pants pantsbuild.pants.contrib.confluence pantsbuild.pants.contrib.go pantsbuild.pants.contrib.node pantsbuild.pants.contrib.python.checks pantsbuild.pants.contrib.scalajs pantsbuild.pants.contrib.scrooge pantsbuild.pants.contrib.avro pantsbuild.pants.contrib.googlejavaformat pantsbuild.pants.testinfra'
export PEX_DOWNLOAD_PREFIX='https://some/internal/url'

@jsirois
Copy link
Contributor

jsirois commented Jan 29, 2019

Alright - there are a host of issues here. The checker tool is mainly a red herring. The primary issue to contend with is building a comprehensive pex that must run some or all portions under python2 and python3. After some quick experiments, fwict, a pex supporting this cannot be built in-general. In specific cases it can happen to work - namely when all relevant dists and their transitivie deps have py2.py3 wheels published / resolvable. In general though this precondition can't be relied upon, and in the specific case of future here we hit the problem. I'll take some more time to think about this and break out relevant pex issue(s) after a bit more experimentation.

@stuhood
Copy link
Member Author

stuhood commented Jan 29, 2019

@jsirois : Thank you for thinking about this.

In terms of short term workarounds, might it be a reasonable hack to temporarily rename the future wheel file to "tag" it py2.py3 before uploading in the wheel builder shard?

Empirically, everything other than style checking is working in our environment, so while there is undoubtedly more work to do to unblock a universal pex, the primary case that we need to unblock the next stable release is the ability to check Py3 code from a Py2/single-python pex.

@jsirois
Copy link
Contributor

jsirois commented Jan 29, 2019

I think it would be more reasonable to remove the future dependency from the checker. Looks like we only do:

contrib/python/src/python/pants/contrib/python/checks/checker/except_statements.py:from future.utils import PY3
contrib/python/src/python/pants/contrib/python/checks/checker/missing_contextmanager.py:from future.utils import PY3
contrib/python/src/python/pants/contrib/python/checks/checker/print_statements.py:from future.utils import PY3

Seems to me not worth the baggage of building a fake wheel when the dep can be dropped with a few lines of code in, say, common.py: https://github.com/pantsbuild/pants/blob/f30c612f7b9c70e0b1f4cf234d8c9155a8b27508/contrib/python/src/python/pants/contrib/python/checks/checker/common.py

@jsirois
Copy link
Contributor

jsirois commented Jan 29, 2019

Actually - it already deps on six - which is well behaved. I'll spin up a quick PR.

stuhood pushed a commit that referenced this issue Jan 29, 2019
### Problem

`future==0.16.0` cannot be resolved in the context of `linux_x86_64-cp-36-cp36m` (see the subtext of #7158), and it seems likely that `future==0.17.1` can be, since its pypi entry claims compatibility with python 3.6. Either way, updating to the most recent version seems win-win.

### Solution

Update to `future==0.17.1`.
jsirois added a commit that referenced this issue Jan 29, 2019
PEX does not support multi-python pexes in-general and in-particular it
cannot properly build a pex for a py2/3 compatible sdist today. Work
around this limitation by removing future (which is distributed as an
sdist) from the checker deps.

Hack to workaround #7158
@jsirois
Copy link
Contributor

jsirois commented Jan 29, 2019

#7178 is confirmed working as a workaround using the example py3 linting target I posted a diff of above:

$ PEX_VERBOSE=9 PANTS_PEX_PACKAGES='pantsbuild.pants pantsbuild.pants.contrib.confluence pantsbuild.pants.contrib.go pantsbuild.pants.contrib.node pantsbuild.pants.contrib.python.checks pantsbuild.pants.contrib.scalajs pantsbuild.pants.contrib.scrooge pantsbuild.pants.contrib.avro pantsbuild.pants.contrib.googlejavaformat pantsbuild.pants.testinfra' build-support/bin/release.sh -p
...
$ ./dist/pants.1.14.0.dev3+097e19e9.pex lint contrib/python/examples/::

12:01:57 00:00 [main]
               See a report at: http://localhost:42959/run/pants_run_2019_01_29_12_01_58_260_f02e7e51b4a145bfb60c83dc1d169a55
12:01:58 00:01   [setup]
12:01:58 00:01     [parse]
               Executing tasks in goals: bootstrap -> imports -> unpack-jars -> deferred-sources -> gen -> jvm-platform-validate -> native-compile -> resolve -> lint
12:01:58 00:01   [bootstrap]
12:01:58 00:01     [substitute-aliased-targets]
12:01:58 00:01     [jar-dependency-management]
12:01:58 00:01     [bootstrap-jvm-tools]
12:01:58 00:01     [provide-tools-jar]
12:01:58 00:01   [imports]
12:01:58 00:01     [ivy-imports]
12:01:58 00:01   [unpack-jars]
12:01:58 00:01     [unpack-jars]
12:01:58 00:01   [deferred-sources]
12:01:58 00:01     [deferred-sources]
12:01:58 00:01   [gen]
12:01:58 00:01     [antlr-java]
12:01:58 00:01     [antlr-py]
12:01:58 00:01     [jaxb]
12:01:58 00:01     [protoc]
12:01:58 00:01     [ragel]
12:01:58 00:01     [thrift-java]
12:01:58 00:01     [thrift-py]
12:01:58 00:01     [grpcio-prep]
12:01:58 00:01     [grpcio-run]
12:01:58 00:01     [wire]
12:01:58 00:01     [avro-java]
12:01:58 00:01     [go-thrift]
12:01:58 00:01     [go-protobuf]
12:01:58 00:01     [jax-ws]
12:01:58 00:01     [scrooge]
12:01:58 00:01     [thrifty]
12:01:58 00:01   [jvm-platform-validate]
12:01:58 00:01     [jvm-platform-validate]
12:01:58 00:01   [native-compile]
12:01:58 00:01     [conan-prep]
12:01:59 00:02     [native-third-party-fetch]
12:01:59 00:02     [c-for-ctypes]
12:01:59 00:02     [cpp-for-ctypes]
12:01:59 00:02   [resolve]
12:01:59 00:02     [ivy]
12:01:59 00:02     [coursier]
12:01:59 00:02     [go]
12:01:59 00:02     [scala-js-compile]
12:01:59 00:02     [scala-js-link]
12:01:59 00:02     [node]
12:01:59 00:02   [lint]
12:01:59 00:02     [scalafix]
                   Skipping scalafix
12:01:59 00:02     [scalafmt]
                   Skipping scalafmt
12:01:59 00:02     [scalastyle]
12:01:59 00:02     [checkstyle]
12:01:59 00:02     [jvm-dep-check]
12:01:59 00:02     [go]
12:01:59 00:02     [google-java-format]
                   Skipping google-java-format
12:01:59 00:02     [javascriptstyle]
12:01:59 00:02     [python-eval]
                   Skipping python-eval
12:01:59 00:02     [pythonstyle]
                   Invalidated 1 target.
12:01:59 00:02       [build-checker]
12:01:59 00:02       [pythonstyle]
                     
                     T302:ERROR   contrib/python/examples/src/python/three/lint.py:004 Expected 2 blank lines, found 1
                          |def func2():
                     
                     
FAILURE: 1 Python Style issues found. You may try `./pants fmt <targets>`


               Waiting for background workers to finish.
12:02:00 00:03   [complete]
               FAILURE

@stuhood
Copy link
Member Author

stuhood commented Jan 29, 2019

Thank you John: have confirmed that this fix works in the case in the description in our repo. Would closing this in favor of #6450 be reasonable, or should I open something to cover the specific case of "the checker's dep's need to be maximally compatible"?

@jsirois
Copy link
Contributor

jsirois commented Jan 29, 2019

Closing in favor of #6450 is reasonable since that work will be blocked on the series of pex issues that need to be resolved to support the pex side of that issue - which I've added a note about.

@jsirois jsirois closed this as completed Jan 29, 2019
cosmicexplorer added a commit that referenced this issue Mar 8, 2019
…7340)

This reverts commit 3a81e86.

### Problem

The use of the `asttokens` library, now within the pythonstyle checker pex, is causing a variant of #7158 when consumed outside of this repo. Additionally, some files fail to parse with:
```
    for tok in tokenize.generate_tokens(StringIO(str_node_text).readline):
  File "/opt/ee/python/2.7/lib/python2.7/tokenize.py", line 374, in generate_tokens
    ("<tokenize>", lnum, pos, line))
  File "<tokenize>", line 3
    "else echo 'no_op'; fi)"
```

Suppressing the lint only works if the lint runs without error, so this makes it impossible to consume outside of the pants repo right now (or at least, impossible in a lot of repos outside of the pants repo).

### Solution

- Revert #7286.

### Result

This will be unreverted asap when the above issues are investigated and fixed.
stuhood pushed a commit that referenced this issue Mar 13, 2019
### Problem

The workaround for #7158 was to remove usage of `future` in the python style `checker` pex, but documentation was not left behind to defend against re-addition, and so it regressed.

### Solution

Switch from `future` to `six`, and add a comment.

### Result

Checking py3 code from within a py2 pex should work.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants