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

Different Python build vs test (if Python not explicitly listed) #835

Closed
jakirkham opened this issue Mar 16, 2016 · 11 comments
Closed

Different Python build vs test (if Python not explicitly listed) #835

jakirkham opened this issue Mar 16, 2016 · 11 comments
Labels
locked [bot] locked due to inactivity stale::closed [bot] closed after being marked as stale stale [bot] marked as stale due to inactivity

Comments

@jakirkham
Copy link
Member

If I have a recipe for a package that consist of the meta.yaml and some simple build scripts, it turns out the python used for the build and test will be different.

# file: meta.yaml
package:
        name: dep_numpy_a
        version: 1.0.0

requirements:
        build:
                - nomkl
                #- python
                - numpy
        run:
                - nomkl
                #- python
                - numpy

build:
        number: 0
        features:
                - nomkl

Here is the build result. Note that it used Python 2.7 for the build and Python 3.5 for the testing phase. Also, note that the final package does not depend on Python (or its version) even though it is an implicit dependency (via numpy).

$ conda build dep_numpy_a
Removing old build environment
Removing old work directory
BUILD START: dep_numpy_a-1.0.0-nomkl_0
Using Anaconda Cloud api site https://api.anaconda.org
Fetching package metadata: ......
Solving package specifications: ..........

The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    nomkl-1.0                  |                0          402 B  defaults
    numpy-1.10.4               |     py27_nomkl_1         6.0 MB  defaults
    setuptools-20.2.2          |           py27_0         453 KB  defaults
    ------------------------------------------------------------
                                           Total:         6.4 MB

The following NEW packages will be INSTALLED:

    libgfortran: 3.0-0               defaults
    nomkl:       1.0-0               defaults
    numpy:       1.10.4-py27_nomkl_1 defaults [nomkl]
    openblas:    0.2.14-4            defaults
    openssl:     1.0.2g-0            defaults
    pip:         8.1.0-py27_0        defaults
    python:      2.7.11-0            defaults
    readline:    6.2-2               defaults
    setuptools:  20.2.2-py27_0       defaults
    sqlite:      3.9.2-0             defaults
    tk:          8.5.18-0            defaults
    wheel:       0.29.0-py27_0       defaults
    zlib:        1.2.8-0             defaults

Fetching packages ...
nomkl-1.0-0.ta 100% |#############################################################################################| Time: 0:00:00 474.56 kB/s
numpy-1.10.4-p 100% |#############################################################################################| Time: 0:00:01   5.25 MB/s
setuptools-20. 100% |#############################################################################################| Time: 0:00:00   1.74 MB/s
Extracting packages ...
[      COMPLETE      ]|################################################################################################################| 100%
Linking packages ...
[      COMPLETE      ]|################################################################################################################| 100%
Removing old work directory
Copying /conda_features_test/dep_numpy_a to /opt/conda2/conda-bld/work
Package: dep_numpy_a-1.0.0-nomkl_0
source tree in: /opt/conda2/conda-bld/work
+ echo 'Building "dep_numpy_a" tracking "nomkl"'
Building "dep_numpy_a" tracking "nomkl"
number of files: 0
Fixing permissions
Fixing permissions
BUILD END: dep_numpy_a-1.0.0-nomkl_0
TEST START: dep_numpy_a-1.0.0-nomkl_0
Fetching package metadata: ......
Solving package specifications: ..........

The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    dep_numpy_a-1.0.0          |          nomkl_0          709 B  file:///opt/conda2/conda-bld/linux-64/

The following NEW packages will be INSTALLED:

    dep_numpy_a: 1.0.0-nomkl_0       file:///opt/conda2/conda-bld/linux-64/ [nomkl]
    libgfortran: 3.0-0               defaults                              
    nomkl:       1.0-0               defaults                              
    numpy:       1.10.4-py35_nomkl_1 defaults                               [nomkl]
    openblas:    0.2.14-4            defaults                              
    openssl:     1.0.2g-0            defaults                              
    pip:         8.1.0-py35_0        defaults                              
    python:      3.5.1-0             defaults                              
    readline:    6.2-2               defaults                              
    setuptools:  20.2.2-py35_0       defaults                              
    sqlite:      3.9.2-0             defaults                              
    tk:          8.5.18-0            defaults                              
    wheel:       0.29.0-py35_0       defaults                              
    xz:          5.0.5-1             defaults                              
    zlib:        1.2.8-0             defaults                              

Fetching packages ...
dep_numpy_a-1. 100% |#############################################################################################| Time: 0:00:00   1.66 MB/s
Extracting packages ...
[      COMPLETE      ]|################################################################################################################| 100%
Linking packages ...
[      COMPLETE      ]|################################################################################################################| 100%
+ echo 'Testing "dep_numpy_a" tracking "nomkl"'
Testing "dep_numpy_a" tracking "nomkl"
TEST END: dep_numpy_a-1.0.0-nomkl_0
# If you want to upload this package to anaconda.org later, type:
#
# $ anaconda upload /opt/conda2/conda-bld/linux-64/dep_numpy_a-1.0.0-nomkl_0.tar.bz2
#
# To have conda build upload to anaconda.org automatically, use
# $ conda config --set anaconda_upload yes

Explicitly stating Python is a dependency or uncommenting the lines above results in the same Python version being used (2.7 in this case).

Build system information.

$ conda info
Using Anaconda Cloud api site https://api.anaconda.org
Current conda install:

             platform : linux-64
        conda version : 4.0.4
  conda-build version : 1.19.2
       python version : 2.7.11.final.0
     requests version : 2.9.1
     root environment : /opt/conda2  (writable)
  default environment : /opt/conda2
     envs directories : /opt/conda2/envs
        package cache : /opt/conda2/pkgs
         channel URLs : https://repo.continuum.io/pkgs/free/linux-64/
                        https://repo.continuum.io/pkgs/free/noarch/
                        https://repo.continuum.io/pkgs/pro/linux-64/
                        https://repo.continuum.io/pkgs/pro/noarch/
          config file : /root/.condarc
    is foreign system : False
@stuarteberg
Copy link
Contributor

Fundamentally, the issue is that recipes that depend on numpy should always list their python dependency explicitly. (This is a reasonable requirement because that is actually how the true dependency graph should look for such programs.)

All programs that depend on python should explicitly state the version of python they use via:

requirements:
  build:
    - python {{PY_VER}}*

  run:
    - python {{PY_VER}}*

But if you're sloppy about it, conda-build tries to help you out with some special case logic when it converts your requirements to MatchSpecs. (Called from here.)

However, that special case logic only checks your top-level requirements. It doesn't look at the full set of dependencies after the solver has been executed. IMHO, I think attempting to handle the general case would make this special case logic even uglier than it already is.

Since it's technically an error (logically) not to mention python in a recipe that lists numpy, I would be in favor of adding an explicit check in ms_depends() that raises an error for such recipes. That would help users avoid the error you ran into, and would force recipes to follow "explicit is better than implicit" in the case of python and numpy.

@jakirkham
Copy link
Member Author

Having an error here seems reasonable.

Though I picked numpy for this example, this can occur with other Python dependent packages and should still be an error in those cases too.

@stuarteberg
Copy link
Contributor

this can occur with other Python dependent packages and should still be an error in those cases too.

Hmm, that's a good point. I'm not sure what right option is here. I mean, at the end of the day, conda-build doesn't have AI: It can't tell you what your requirements list should say in the general case. But there are a lot of little examples like this where we could tell the user on a case-by-case basis that we think he's doing it wrong.

One big temptation -- and a big mistake -- would be for conda-build to "help the user out" by silently "fixing" his recipe or inferring extra semantics when we think he left something out. (An example of this is how conda will pick a version of python for you (2 vs 3) if you don't specify one explicitly. It definitely encourages violations of "explicit is better than implicit".) Once such special-case logic is added to conda, it can never be removed, because recipes will be written to depend on it (perhaps unknowingly).

A better way to handle bad recipes would be to have a special module in conda-build that serves as a "linter" for recipes to tell users what mistakes they've made. Then, instead of trying to support one special case after another in the conda code base, the world will simply be populated with well-formed recipes. If we ever decide to relax a linter rule, no problem: just remove or edit the rule. Existing packages will continue to have the same semantics that they always had.

What do you think?

@jakirkham
Copy link
Member Author

Definitely agree that more of these quiet changes should be turned into errors, but there probably should be a phase out (warning/deprecation period) first.

I think I agree with having a linter ( conda lint :) ).

Having this logic in conda build does make things more complicated. If anything at all, conda build should call the linter first and then proceed.

@jakirkham
Copy link
Member Author

@pelson and @ocefpaf, do you think some of the existing linting tools used at conda-forge could be leveraged here? Do you have any thoughts on linting rules?

@ocefpaf
Copy link
Contributor

ocefpaf commented Mar 17, 2016

Not sure how to implement that. If I got it right the linter must know the python dependencies for each package before inspecting the recipes for that to work, right?

But if you're sloppy about it, conda-build tries to help you out with some special case logic when it converts your requirements to MatchSpecs.

Maybe conda-build should just raise an instead of trying to help 😉

@jakirkham
Copy link
Member Author

So, to be clear. This is not a totally theoretical issue as it can cause problems when building on Windows.

jschueller added a commit to jschueller/conda-recipes that referenced this issue Apr 13, 2016
Apparently packages depending on numpy should always list their python dependency explicitly:
conda/conda-build#835

This fixes the build for another version than the default version in conda-build.
jschueller added a commit to jschueller/conda-recipes that referenced this issue Apr 13, 2016
apparently packages that depend on numpy should always list their python dependency explicitly:
conda/conda-build#835

this fixes the build for another python version:
```conda build --python 3.4 python/nlopt```
jschueller added a commit to jschueller/conda-recipes that referenced this issue Apr 14, 2016
Apparently packages depending on numpy should always list their python dependency explicitly:
conda/conda-build#835
jschueller added a commit to jschueller/conda-recipes that referenced this issue Apr 14, 2016
Apparently packages depending on numpy should always list their python
dependency explicitly:
conda/conda-build#835
jschueller added a commit to jschueller/conda-recipes that referenced this issue Apr 14, 2016
apparently packages that depend on numpy should always list their python
dependency explicitly:
conda/conda-build#835

this fixes the build for another python version:
```conda build --python 3.4 python/nlopt```
jschueller added a commit to jschueller/conda-recipes that referenced this issue Apr 14, 2016
apparently packages that depend on numpy should always list their python
dependency explicitly:
conda/conda-build#835

this fixes the build for another python version:
```conda build --python 3.4 python/nlopt```
@patricksnape
Copy link
Contributor

@jakirkham @msarahan I think this is related to the problems we've been seeing over at conda-forge. Though not related to numpy in this case.

If you build a package that does not explicitly require Python, but you are activating features (such as vc* on Windows) then you must explicitly pin the Python version in the test requires using PY_VER, otherwise you will get the version of Python from the root environment. For example:

package:
  name: testbug
  version: 1.0

requirements:
  build:
    - python

build:
  script: python --version

test:
  requires:
    - python

  commands: 
    - python --version
    - which python

will print 3.5 when run with CONDA_PY=35 for the script, but say 2.7 for the test (assuming the root environment is 2.7). This certainly doesn't seem like correct behaviour.

mingwandroid pushed a commit to mingwandroid/conda-recipes that referenced this issue Apr 21, 2016
apparently packages that depend on numpy should always list their python
dependency explicitly:
conda/conda-build#835

this fixes the build for another python version:
```conda build --python 3.4 python/nlopt```
@jakirkham
Copy link
Member Author

So, I have been thinking about this a bit more and basically the bug is simply a failure to identify the transitive property of packages. Namely if I depend on things that depend on python, then it should be deduced that I depend on python. Given this is a remarkably simple and desirable property, I don't think it is reasonable to expect conda and conda-build to understand this.

cc @isuruf

@scopatz
Copy link
Contributor

scopatz commented May 30, 2019

I just hit this again in the vitables-feedstock: conda-forge/vitables-feedstock#10

@github-actions
Copy link

Hi there, thank you for your contribution!

This issue has been automatically marked as stale because it has not had recent activity. It will be closed automatically if no further activity occurs.

If you would like this issue to remain open please:

  1. Verify that you can still reproduce the issue at hand
  2. Comment that the issue is still reproducible and include:
    - What OS and version you reproduced the issue on
    - What steps you followed to reproduce the issue

NOTE: If this issue was closed prematurely, please leave a comment.

Thanks!

@github-actions github-actions bot added the stale [bot] marked as stale due to inactivity label May 19, 2022
@github-actions github-actions bot added the stale::closed [bot] closed after being marked as stale label Jun 19, 2022
@github-actions github-actions bot added the locked [bot] locked due to inactivity label Jun 19, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
locked [bot] locked due to inactivity stale::closed [bot] closed after being marked as stale stale [bot] marked as stale due to inactivity
Projects
None yet
Development

No branches or pull requests

5 participants