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

Fix edge case when building packages with optional c extensions #421

Merged
merged 2 commits into from
Jul 25, 2017

Conversation

stealthycoin
Copy link
Contributor

The edge case occurs when a package can compile optional c speedups
which succeed during the build process but lock the generated wheel file
to the arch the package was built on. This makes the wheel file
incompatible with lambda and causes it to fail to add that dependency
even though it could have by building it without the optional c
extensions.

This is a bit tricky to fix as means we need to selectively break the
ability to compile c extensions during some runs of our wheel building
phase. It is also quite different on POSIX and Windows.

cc @kyleknap @jamesls @dstufft

The edge case occurs when a package can compile optional c speedups
which succeed during the build process but lock the generated wheel file
to the arch the package was built on. This makes the wheel file
incompatible with lambda and causes it to fail to add that dependency
even though it could have by building it without the optional c
extensions.

This is a bit tricky to fix as means we need to selectivly break the
ability to compile c extensions during some runs of our wheel buiding
phase. It is also quite differnet on POSIX and Windows.
@codecov-io
Copy link

codecov-io commented Jul 22, 2017

Codecov Report

Merging #421 into master will decrease coverage by 0.59%.
The diff coverage is 63.63%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master     #421     +/-   ##
=========================================
- Coverage   93.54%   92.94%   -0.6%     
=========================================
  Files          18       18             
  Lines        2805     2850     +45     
  Branches      369      374      +5     
=========================================
+ Hits         2624     2649     +25     
- Misses        133      150     +17     
- Partials       48       51      +3
Impacted Files Coverage Δ
chalice/compat.py 48.57% <21.73%> (-51.43%) ⬇️
chalice/deploy/packager.py 95.66% <93.75%> (-0.33%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 629ae01...aaa4106. Read the comment docs.

Copy link
Member

@jamesls jamesls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable given what we have to work with.

I think we should start adding integration tests for the packager. Something where we give it various requirements.txt files and verify it does the right thing. I get that it it'll vary per platform but I think the extra safety net would be a good thing. We can address that as a separate PR if you want.

if os.name == 'nt':
# windows
# On windows running python in a subprocess with no environment variables
# will cause sevral issues. In order for our subprocess to run normally we
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/sevral/several

if 'SYSTEMROOT' in os.environ:
subprocess_python_base_environ['SYSTEMROOT'] = os.environ['SYSTEMROOT']

# This is the acutal patch used on windows to prevent distutils from
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/acutal/actual

# This is the acutal patch used on windows to prevent distutils from
# compiling C extensions. The msvc compiler base class has its compile
# method overridden to raise a CompileError. This can be caught by
# setup.py code which can then fallback to making a purepython
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/purepython/pure python/

# `prevent_msvc_compiling_patch` and extra escapes have been added on line
# 5 because it is passed through another layer of string parsing before it
# is executed.
_SETUPTOOLS_SHIM = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The escaping makes this hard to read. Could you just use r""" to avoid all the double escaping?

# _SETUPTOOLS_SHIM.
pip_no_compile_c_shim = (
"import pip;"
"pip.wheel.SETUPTOOLS_SHIM = \"\"\"%s\"\"\";"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing. Can you use r""" to cut down on the amount of escaping needed?

"import pip;"
"pip.wheel.SETUPTOOLS_SHIM = \"\"\"%s\"\"\";"
) % _SETUPTOOLS_SHIM
pip_no_compile_c_env_vars = {} # type: ignore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd still like to get these typed. These are passed to code that we own in package.py.

Copy link
Member

@JordonPhillips JordonPhillips left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably mention in the docs that pre-building may get better speed for optional c extensions. Otherwise this looks great all things considered.

# setup.py code which can then fallback to making a purepython
# package if possible.
# We need mypy to ignore these since they are never actually called from
# within ourprocess they do not need to be a part of our typechecking
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/ourprocess/our process/

@@ -374,12 +384,25 @@ def _download_dependencies(self, directory, requirements_filename):

# Re-count the wheel files after the second download pass. Anything
# that has an sdist but not a valid wheel file is still not going to
# work on lambda and our last ditch effort is to try and build the
# sdists into wheel files.
# work on lambda and our we must now try and build the sdist into a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/our we must now/we must now/


* A package is installable with ``requirements.txt`` but has optional c
extensions. Chalice can build the dependency without the c extensions, but
if you want better performance you can vendor a version taht is compiled.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/taht/that

Also a couple minor changes to the shim strings to make them more
readable.
@stealthycoin stealthycoin merged commit 2ed6e64 into aws:master Jul 25, 2017
@stealthycoin stealthycoin deleted the fix-optional-c-ext branch July 25, 2017 17:56
@jamesls jamesls mentioned this pull request Jul 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants