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

Turn off compilation #715

Closed
wants to merge 4 commits into from
Closed

Turn off compilation #715

wants to merge 4 commits into from

Conversation

ivoflipse
Copy link

I added an option to the build section where you can say:

pyc_compilation: False

and it will skip the pyc compilation step.

This should address #686 and #709. Hope I changed it correctly, though I verified that it works.

remove_easy_install_pth(files, preserve_egg_dir=preserve_egg_dir)
rm_py_along_so()
if config.CONDA_PY < 30:
if config.CONDA_PY < 30 and pyc_compilation:
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is compilation only done for Python 2? @ivoflipse you're perhaps not the right one to ask, since you're only maintaining this behavior, but maybe @ilanschnell or @groutr know?

Copy link
Author

Choose a reason for hiding this comment

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

I don't know, but it probably has to with Python 3 stuff compiled files in a __pycache__ folder

I haven't been able to use Python 3 much until recently, so now a lot of these Python 2/3 issues start creeping up on me :-)

@msarahan
Copy link
Contributor

+1 from me. The Travis error is just Github complaining about too many requests. Looks OK. I think this is a good addition, in case things should not be compiled for any reason.

The danger here is that compilation is a good last check of package validity. People may shoot themselves in the foot with this and distribute broken packages more easily. Still, the issues mentioned above present valid reasons for this change.

@ivoflipse
Copy link
Author

Yeah I currently had the compilation lines commented out, but that's obviously not what I want either. Because then it no longer works for package that do require it.

One alternative solution would be to specify that I want certain parts of the package's code to be excluded. Either through changing setup.py or by removing them from the package after python setup.py install in the build.bat/sh. Sadly, when creating conda package for code I don't maintain, I don't always have the option to fix setup.py without forking the project or submitting a PR.

Another would be to have it try compiling every file, but only raise an exception if this field is set. That way you can chose to ignore errors that you were expecting, but you'd still get compilation of all your other files.

@ivoflipse
Copy link
Author

I've been looking into a way to add a list of modules to exclude from compilation, but the code doesn't seem to lend itself to these purposes at all. I had hoped to use the same syntax as imports for testing use, but I didn't manage to find a good way of whitelisting/blacklisting files.

The current code basically just passes the entire site-packages directory to compileall.py, which probably knows how to deal with all sorts of different scenarios. So I'm worried that even if I got it working in my case, I would come up with a nice general solution. I think the reason Python 3 is excluded (wrongly) is because the current code checks whether the same folder includes a .pyc version of the same file. If any is found, it will turn on the compilation flag. But since on Python 3 those .pyc files live inside the pycache folder, so this check would go over the entire sp_dir and never return True.

For now, I think this solution of optionally turning off compilation completely will at least prevent broken builds for misbehaving packages. Personally I don't think the .pyc compilation is that useful, if you want to know if your code works, include a test suite or at least try some import tests (which support platform filters).

@ivoflipse
Copy link
Author

@msarahan Any idea on how to proceed with this PR?

@msarahan
Copy link
Contributor

msarahan commented Feb 3, 2016

Can you come up with a quick test recipe for with/without this option? I don't think it's strictly necessary, but it would be nice to have this feature covered. Otherwise, please pull and merge or rebase to fix the conflict.

I think this warrants further discussion about why we're doing compiling, but it seems like now is not the right time - and the gradual Python 3 migration may obviate this issue anyway.

@jakirkham
Copy link
Member

Personally, I think we should be having people set PYTHONDONTWRITEBYTECODE in these cases instead of adding yet another way to accomplish this, but that is only my opinion.

@ivoflipse
Copy link
Author

@jakirkham any hints on where in conda this is used already? I haven't had time to rebase the PR yet, but I hope to do so soon

@msarahan
Copy link
Contributor

I don't think this is currently used in conda currently. People set that evironment variable independently of conda. Having a conda command line flag that sets it may help it feel more "native" - but is also sort of against Python's "only one right way to do it" philosophy. I don't have a strong opinion here. Either documenting this environment variable better in the conda docs or creating your config would work, and both require documentation at a minimum. I generally prefer your recipe approach because environment variables are easy to forget and not portable.

@jakirkham
Copy link
Member

Hmm...so I have played around with this a bit more and given this some more thought.

Maybe the better question is why are we going through the Python tree and compiling Python files that weren't compiled previously. It seems that is the real problem and maybe the simplest answer is that we should not do this. Unfortunately, the commit that added that compile_missing_pyc gave no real explanation. Any thoughts @ilanschnell?

@Korijn
Copy link
Contributor

Korijn commented Feb 25, 2016

Would be nice to have this. E.g. django 1.9 contains jinja templates with .py extensions, so without this PR you cannot package it (it will try to compile them and crash on the jinja syntax).

@msarahan
Copy link
Contributor

Ping @kalefranz. We discussed this in a recent meeting, and people expressed concern about packages without pyc files running slower. @groutr pointed out to me that we could always write pyc files at install time, because at install time by definition have write permissions.

@Korijn
Copy link
Contributor

Korijn commented Feb 25, 2016

I can understand this, but how does that resolve the issue for the django 1.9 scenario I mentioned in #715 (comment)?

@msarahan
Copy link
Contributor

It doesn't. I would prefer to have conda never compile to pyc, and rely on the installed python to compile as necessary at runtime. Others argued that we may not always have write permission at runtime, and need to ship pyc files somehow.

If anyone ever tries to compile django's templates, it will fail, no matter when they are compiled, as you point out.

@Korijn
Copy link
Contributor

Korijn commented Feb 28, 2016

Not having write permissions is a good argument. So having a blacklist as proposed here seems like an approach that is compatible with current use cases.

@ijstokes
Copy link

ijstokes commented May 2, 2016

I am facing this issue with https://github.com/sloria/webargs and have submitted this issue on that repo: marshmallow-code/webargs#105

Here are my thoughts:

  • We have space-constrained systems where doubling up with .py and .pyc files is problematic, so that is an additional consideration for a mechanism to disable .pyc file creation.
  • If there is a cross-platform way of doing something Python specific through PYTHONDONTWRITEBYTECODE (as noted above) then that seems like the best way to proceed
  • It looks like conda-build doesn't respect that environment variable, and will always do the byte-compile phase, so I would recommend/request that conda-build be updated to respect that variable (trace below).
  • Conda build documentation would need to be updated accordingly to describe how it would respond to this environment variable being set.
  • I do not take a position on whether or not the default should be to create a .pyc file ...
  • ... but I do think there should be mechanisms that either can be achieved (.pyc file creation managed by conda or no .pyc file creation from conda, and just "whatever Python does" default behavior).
  • I do not take a position on whether .pyc file creation, when it happens thanks to conda (again, which I think should be configurable), should be done at package build time or package install time.

@ijstokes
Copy link

ijstokes commented May 2, 2016

Here is a trace from a concrete example based on this webargs fork https://github.com/ijstokes/webargs (only just to add in the conda.recipe directory):

$ conda build conda.recipe/
Removing old build environment
Removing old work directory
BUILD START: webargs-1.3.2-py27_0
Using Anaconda Cloud api site https://api.anaconda.org
Fetching package metadata: ......
Solving package specifications: .........

The following NEW packages will be INSTALLED:

    marshmallow: 2.7.2-py27_0 
    openssl:     1.0.2g-0     
    pip:         8.1.1-py27_1 
    python:      2.7.11-0     
    readline:    6.2-2        
    setuptools:  20.7.0-py27_0
    sqlite:      3.9.2-0      
    tk:          8.5.18-0     
    wheel:       0.29.0-py27_0
    zlib:        1.2.8-0      

Linking packages ...
[      COMPLETE      ]|############################################################################################| 100%
Removing old work directory
Copying /Users/ijstokes/code/webargs to /Users/ijstokes/anaconda/conda-bld/work
Package: webargs-1.3.2-py27_0
source tree in: /Users/ijstokes/anaconda/conda-bld/work
+ export PYTHONDONTWRITEBYTECODE
+ /Users/ijstokes/anaconda/envs/_build/bin/python setup.py install
running install
running bdist_egg
running egg_info
creating webargs.egg-info
writing requirements to webargs.egg-info/requires.txt
writing webargs.egg-info/PKG-INFO
writing top-level names to webargs.egg-info/top_level.txt
writing dependency_links to webargs.egg-info/dependency_links.txt
writing manifest file 'webargs.egg-info/SOURCES.txt'
reading manifest file 'webargs.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'webargs.egg-info/SOURCES.txt'
installing library code to build/bdist.macosx-10.5-x86_64/egg
running install_lib
running build_py
creating build
creating build/lib
creating build/lib/webargs
copying webargs/__init__.py -> build/lib/webargs
copying webargs/aiohttpparser.py -> build/lib/webargs
copying webargs/async.py -> build/lib/webargs
copying webargs/bottleparser.py -> build/lib/webargs
copying webargs/core.py -> build/lib/webargs
copying webargs/djangoparser.py -> build/lib/webargs
copying webargs/falconparser.py -> build/lib/webargs
copying webargs/fields.py -> build/lib/webargs
copying webargs/flaskparser.py -> build/lib/webargs
copying webargs/pyramidparser.py -> build/lib/webargs
copying webargs/tornadoparser.py -> build/lib/webargs
copying webargs/webapp2parser.py -> build/lib/webargs
creating build/bdist.macosx-10.5-x86_64
creating build/bdist.macosx-10.5-x86_64/egg
creating build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/__init__.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/aiohttpparser.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/async.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/bottleparser.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/core.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/djangoparser.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/falconparser.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/fields.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/flaskparser.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/pyramidparser.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/tornadoparser.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
copying build/lib/webargs/webapp2parser.py -> build/bdist.macosx-10.5-x86_64/egg/webargs
byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/__init__.py to __init__.pyc
byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/aiohttpparser.py to aiohttpparser.pyc
  File "build/bdist.macosx-10.5-x86_64/egg/webargs/aiohttpparser.py", line 84
    yield from req.post()
             ^
SyntaxError: invalid syntax

byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/async.py to async.pyc
  File "build/bdist.macosx-10.5-x86_64/egg/webargs/async.py", line 25
    parsed = yield from self.parse_arg(
                      ^
SyntaxError: invalid syntax

byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/bottleparser.py to bottleparser.pyc
byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/core.py to core.pyc
byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/djangoparser.py to djangoparser.pyc
byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/falconparser.py to falconparser.pyc
byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/fields.py to fields.pyc
byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/flaskparser.py to flaskparser.pyc
byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/pyramidparser.py to pyramidparser.pyc
byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/tornadoparser.py to tornadoparser.pyc
byte-compiling build/bdist.macosx-10.5-x86_64/egg/webargs/webapp2parser.py to webapp2parser.pyc
creating build/bdist.macosx-10.5-x86_64/egg/EGG-INFO
copying webargs.egg-info/PKG-INFO -> build/bdist.macosx-10.5-x86_64/egg/EGG-INFO
copying webargs.egg-info/SOURCES.txt -> build/bdist.macosx-10.5-x86_64/egg/EGG-INFO
copying webargs.egg-info/dependency_links.txt -> build/bdist.macosx-10.5-x86_64/egg/EGG-INFO
copying webargs.egg-info/not-zip-safe -> build/bdist.macosx-10.5-x86_64/egg/EGG-INFO
copying webargs.egg-info/requires.txt -> build/bdist.macosx-10.5-x86_64/egg/EGG-INFO
copying webargs.egg-info/top_level.txt -> build/bdist.macosx-10.5-x86_64/egg/EGG-INFO
creating dist
creating 'dist/webargs-1.3.2-py2.7.egg' and adding 'build/bdist.macosx-10.5-x86_64/egg' to it
removing 'build/bdist.macosx-10.5-x86_64/egg' (and everything under it)
Processing webargs-1.3.2-py2.7.egg
creating /Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages/webargs-1.3.2-py2.7.egg
Extracting webargs-1.3.2-py2.7.egg to /Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages
  File "/Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages/webargs-1.3.2-py2.7.egg/webargs/aiohttpparser.py", line 84
    yield from req.post()
             ^
SyntaxError: invalid syntax

  File "/Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages/webargs-1.3.2-py2.7.egg/webargs/async.py", line 25
    parsed = yield from self.parse_arg(
                      ^
SyntaxError: invalid syntax

Adding webargs 1.3.2 to easy-install.pth file

Installed /Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages/webargs-1.3.2-py2.7.egg
Processing dependencies for webargs==1.3.2
Searching for marshmallow==2.7.2
Best match: marshmallow 2.7.2
Adding marshmallow 2.7.2 to easy-install.pth file

Using /Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages
Finished processing dependencies for webargs==1.3.2
found egg dir: /Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages/webargs-1.3.2-py2.7.egg
compiling .pyc files...
Compiling /Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages/webargs/aiohttpparser.py ...
  File "/Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages/webargs/aiohttpparser.py", line 84
    yield from req.post()
             ^
SyntaxError: invalid syntax

Compiling /Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages/webargs/async.py ...
  File "/Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages/webargs/async.py", line 25
    parsed = yield from self.parse_arg(
                      ^
SyntaxError: invalid syntax

Command failed: /Users/ijstokes/anaconda/envs/_build/bin/python -Wi /Users/ijstokes/anaconda/envs/_build/lib/python2.7/compileall.py -q -x port_v3 /Users/ijstokes/anaconda/envs/_build/lib/python2.7/site-packages

@msarahan
Copy link
Contributor

msarahan commented May 5, 2016

@ivoflipse I'd like to merge this. Can you merge the conflicts, or would you rather I do it?

And added a check for this in post.py
Also updated the recipe, so I could build a new package to try it out
Also changed it so build.py checks the meta.yaml value
@ivoflipse
Copy link
Author

There @msarahan I think I cleaned it up.

@msarahan
Copy link
Contributor

msarahan commented May 6, 2016

Errors appear to be ours, due to recent open SSL update. I will close and reopen this PR to redo the CI once we have those errors sorted.

Cc @csoja @kalefranz @ilanschnell

@kalefranz
Copy link
Contributor

@ijstokes et al.,

We should consider the inverse case of distributing only .pyc files--instead of only .py files--in a space-confined environment. Python is going to make those pyc files anyway if it can (i.e. permissions allow and PYTHONDONTWRITEBYTECODE not set).

@kalefranz
Copy link
Contributor

Also agree the conda-build should be passing all environment variables through to both the jinja2 context and the build recipe. That would include PYTHONDONTWRITEBYTECODE.

@jakirkham
Copy link
Member

jakirkham commented May 6, 2016

@kalefranz, this might be of interest to you. We considered allowing one to define the environment variables in the meta.yaml as proposed here ( #767 ). In the end, we didn't go with it.

Though if are wanting to do something similar with PYTHONDONTWRITEBYTECODE, that would be a way to do it. The syntax would remain simple here.

Also, it may be a way (combined with some sort of prep step to set things like CPU_COUNT, @msarahan. Though the latter is off topic.

@msarahan
Copy link
Contributor

As of the 1.21.11 release, we now try to compile, but do not crash on failure. This was added by @minrk in #1146. I think this closes this issue - but please reopen or open a new issue if we need further discussion.

@msarahan msarahan closed this Aug 10, 2016
@msarahan
Copy link
Contributor

Also, more current work in #1169

@ivoflipse ivoflipse deleted the turn-off-compilation branch August 10, 2016 07:13
@github-actions github-actions bot added the locked [bot] locked due to inactivity label May 13, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 13, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
locked [bot] locked due to inactivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants