pytest icon indicating copy to clipboard operation
pytest copied to clipboard

--pyargs discovery for zipped packages/unpacked wheels/eggs

Open bjodah opened this issue 9 years ago • 13 comments

EDIT:

Using py.test --pyargs mypackage does not seem to work for .egg distributed packages. Adding

[easy_install]
zip_ok = False

to setup.cfg seems to be a viable fix until py.test supports zipped packages.

Original issue text:

Using py.test --pyargs mypackage under a conda environment seems to be broken. I've reported it here: https://github.com/conda/conda/issues/2075

I am reposting it here in case someone has an idea what might be going on here. Here is a Dockerfile to reproduce the bug:

FROM continuumio/miniconda:3.19.0
MAINTAINER Björn Dahlgren <[email protected]>
ENV PATH /opt/miniconda2/bin:$PATH
RUN git clone https://github.com/bjodah/dummypkg.git && \
    cd dummypkg && \
    conda install conda-build pytest && \
    conda build conda-recipe && \
    conda install --use-local dummypkg
RUN cd /tmp && \
    python -c 'import dummypkg; print(dummypkg.__file__)' && \
    python -m pytest --pyargs dummypkg

Running docker build generates the following output:

$ docker build revised-docker-environment/
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon 
Step 0 : FROM continuumio/miniconda:3.19.0
 ---> bc9d0fb804ac
Step 1 : MAINTAINER Björn Dahlgren <[email protected]>
 ---> Using cache
 ---> f81cd6785b68
Step 2 : ENV PATH /opt/miniconda2/bin:$PATH
 ---> Using cache
 ---> 3227b31b6bd9
Step 3 : RUN git clone https://github.com/bjodah/dummypkg.git &&     cd dummypkg &&     conda install conda-build pytest &&     conda build conda-recipe &&     conda install --use-local dummypkg
 ---> Using cache
 ---> 6765cf1fae4d
Step 4 : RUN cd /tmp &&     python -c 'import dummypkg; print(dummypkg.__file__)' &&     python -m pytest --pyargs dummypkg
 ---> Running in e9c721e5c4c2
/opt/conda/lib/python2.7/site-packages/dummypkg-0.1.0-py2.7.egg/dummypkg/__init__.pyc
============================= test session starts ==============================
platform linux2 -- Python 2.7.10, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
rootdir: /tmp, inifile: 

========================= no tests ran in 0.00 seconds =========================
ERROR: file or package not found: dummypkg
INFO[0000] The command [/bin/sh -c cd /tmp &&     python -c 'import dummypkg; print(dummypkg.__file__)' &&     python -m pytest --pyargs dummypkg] returned a non-zero code: 4 

bjodah avatar Mar 09 '16 10:03 bjodah

I tried your recipe on Windows (after creating an appropriate bld.bat) without Docker, and I see the same issue. I noticed though that your recipe is creating an egg package:

λ conda package -L dummypkg

INFO: The location for available packages: E:\Miniconda\pkgs
INFO: All files belonging to 'dummypkg-0.1.0-py27_0' package:

E:\Miniconda\pkgs/dummypkg-0.1.0-py27_0/info/files
E:\Miniconda\pkgs/dummypkg-0.1.0-py27_0/info/index.json
E:\Miniconda\pkgs/dummypkg-0.1.0-py27_0/info/recipe.json
E:\Miniconda\pkgs/dummypkg-0.1.0-py27_0/info/recipe/bld.bat
E:\Miniconda\pkgs/dummypkg-0.1.0-py27_0/info/recipe/build.sh
E:\Miniconda\pkgs/dummypkg-0.1.0-py27_0/info/recipe/meta.yaml
E:\Miniconda\pkgs/dummypkg-0.1.0-py27_0/info/recipe/run_test.py
E:\Miniconda\pkgs/dummypkg-0.1.0-py27_0/Lib/site-packages/dummypkg-0.1.0-py2.7.egg
E:\Miniconda\pkgs/dummypkg-0.1.0-py27_0/Lib/site-packages/dummypkg.pth

I'm not sure, but perhaps py.test can't load tests from eggs?

For the record, I added this to your recipe:

build:
  preserve_egg_dir: True

But still the package only contained the .egg file, while I expected it to also contain the egg dir... I don't have time right now to investigate this further, but this might give you some hint.

nicoddemus avatar Mar 09 '16 14:03 nicoddemus

@nicoddemus spot on! This fixes it: https://github.com/bjodah/dummypkg/blob/master/revised2-docker-environment-non-egg/Dockerfile#L7

i.e. the following is added to setup.cfg:

[easy_install]
zip_ok = False

Perhaps a word about this in the docs where --pyargs is discussed is in order? (I could try to write something up and submit a PR if you want).

Just to make things even more complicated there is the issue of zip_ok vs. zip_safe: http://stackoverflow.com/a/34552171/790973

bjodah avatar Mar 10 '16 10:03 bjodah

Cool, thanks for the links. A PR for the docs would be welcome. :grin:

nicoddemus avatar Mar 10 '16 10:03 nicoddemus

We should handle zipped packages

RonnyPfannschmidt avatar Mar 11 '16 10:03 RonnyPfannschmidt

Agree, but perhaps we should edit the description or, better yet, create a new issue and point to this one?

Em sex, 11 de mar de 2016 07:08, Ronny Pfannschmidt < [email protected]> escreveu:

We should handle zipped packages

— Reply to this email directly or view it on GitHub https://github.com/pytest-dev/pytest/issues/1445#issuecomment-195305579.

nicoddemus avatar Mar 11 '16 10:03 nicoddemus

For a package installed in dev mode into my conda environment, my py.tests fail with "cannot import <module_name>". Is this related to this? FYI, my site-packages folder for the conda env contains only a module_name.egg-link entry.

michaelaye avatar Nov 08 '16 06:11 michaelaye

@michaelaye unrelated at first glance, please report with more detail in a new bug so @nicoddemus can investigate

RonnyPfannschmidt avatar Nov 08 '16 14:11 RonnyPfannschmidt

Turned out I had other issues creating my problem, sorry for the noise.

michaelaye avatar Nov 08 '16 15:11 michaelaye

Is this still an open problem? Is it correct to say that pytest can't test a module from a zip file (e.g. PEX, egg, etc) without first extracting the test file?

katzdm avatar Jun 21 '19 23:06 katzdm

Correct

RonnyPfannschmidt avatar Jun 22 '19 07:06 RonnyPfannschmidt

I'm curious @katzdm, what's your use case for pytest to import a module from a zipped package? To run a test suite against a created PEX file to ensure it was correctly built?

nicoddemus avatar Jun 22 '19 22:06 nicoddemus

I've been experimenting with an open-source build system that prefers PEX as the format-of-choice for python "executables". Since tests are "executable", the current implementation assembles a PEX consisting of {application code, test files, pytest, third-party dependencies, test-runner-script}, where the test-runner-script does some initial setup before invoking pytest.main().

I think this model is probably more of an artifact of other design choices, than an endorsement of this as The Best Way to build and run tests. I came across an issue that eventually led me here though, and wanted to make sure I correctly understood the root cause (thanks for the quick reply!)

katzdm avatar Jun 24 '19 13:06 katzdm

Just to add a specific use case:

Downstream packages may want to distribute a zipapp including my package, so I want to exercise all of its functionality when zipped. The most straightforward way I can think to do this would be to use PYTHONPACKAGE=$( ls $PWD/dist/mypkg*.whl ) pytest --pyargs mypkg.

This doesn't currently work, and I can't readily find an alternative approach.

effigies avatar May 28 '24 19:05 effigies