Skip to content

pytest.main function gives an error when tested module is in the PYTHONPATH #3128

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

Closed
jlevertov opened this issue Jan 18, 2018 · 13 comments
Closed
Labels
status: needs information reporter needs to provide more information; can be closed after 2 or more weeks of inactivity topic: collection related to the collection phase type: question general question, might be closed after 2 weeks of inactivity

Comments

@jlevertov
Copy link

Hi,
I created a package for configuring how to run tests - it gets user input and translates it to the necessary pytest flags and command format - this package is called "package a".
And I also created another package in which I write the tests - this package is called "package b"
Both of the packages are packaged as zip file, and added to the PYTHONPATH.
The issue is:
When using pytest.main(args=list of arguments), I get the following error:
E ENOTDIR: [Not a directory]: samefile('path to requested test file', 'path to requested test file inside the zipped tests package - "package b" ').

On the other hand, when running the command as a bash command:
os.system('python -m pytest ...')
everything works perfectly.

A small code example: The not working way

import pytest
pytest.main(args=['path_to_test_file', '-v', '-s'])

A small code example: The working way

import os
os.system('python -m pytest path_to_test_file -v -s')

My specs:
Operating system: Debian 8.1
pytest: 3.3.0 (also tried on version 3.3.2)
py: 1.5.2
six: 1.11.0
setuptools: 38.4.0
attrs: 17.4.0

@jlevertov jlevertov changed the title pytest.main function doesn't gives an error when tested module is in the PYTHONPATH pytest.main function gives an error when tested module is in the PYTHONPATH Jan 18, 2018
@The-Compiler
Copy link
Member

Can you show the full output you get?

@RonnyPfannschmidt RonnyPfannschmidt added the status: needs information reporter needs to provide more information; can be closed after 2 or more weeks of inactivity label Jan 18, 2018
@jlevertov
Copy link
Author

The output I get is only the default header of pytest, and then the error I wrote:
E ENOTDIR: [Not a directory]: samefile('path to requested test file', 'path to requested test file inside the zipped tests package)

@RonnyPfannschmidt
Copy link
Member

without accurate information we are unable to determine whats actually up

@jlevertov
Copy link
Author

Could you tell me the exact info you need?

@RonnyPfannschmidt
Copy link
Member

folder structure, exact invocations and the exact output

@jlevertov
Copy link
Author

jlevertov commented Jan 21, 2018

The exact output: (I forgot to mention that I work with python 2.7)

/usr/local/lib/python2.7/dist-packages/py/_path/local.py:682 in pyimport
   `issame = self.samefile(modfile)`
/usr/local/lib/python2.7/dist-packages/py/_path/local.py:197 in samefile
    `os.path.samefile, self.strpath, other)`
/usr/local/lib/python2.7/dist-packages/py/_error.py:86 in chacked_call
    `raise cls("%s%r" % (func.__name__, args))`
E ENOTDIR: [Not a directory]: samefile('path_to_test_file', 'path_to_test_file_inside_package_b_zip')
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interurupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
============================= 1 error in 0.13 seconds ================================

The exact invocation:

import pytest
result = pytest.main(args=['path_to_test_file', '-v', '-s'])
if not result:
    sys.exit(1)

Folder Structure:

  • /home/My_Project/modules
    • module_a
      • package_a
        • main.py
    • module_b
      • package_b
        • tests
          • test_file.py
  • /home/My_Project/outputs
    • package_a.zip
    • package_b.zip

PYTHONPATH = /home/My_Project/outputs

Therefore,
'path_to_test_file' = /home/My_Project/package_b/tests/test_file.py
'path_to_test_file_inside_package_b_zip' = /home/My_Project/outputs/package_b.zip/package_b/tests/test_file.py

@nicoddemus
Copy link
Member

For zip files to work you need to add the path to the zip file in the PYTHONPATH, not the path to the directory that contains the zip file. IOW, your PYTHONPATH should contain "/home/My_Project/outputs/package_a.zip" and "/home/My_Project/outputs/package_b.zip".

Furthermore, for pytest to be able to import those tests files you will need the --pyargs argument so pytest imports your files as modules: pytest --pyargs package_b.tests.test_file. For that to work on Python 2.7 you will also need __init__.py files to turn your directories into packages.

@nicoddemus nicoddemus added type: question general question, might be closed after 2 weeks of inactivity topic: collection related to the collection phase labels Jan 22, 2018
@jlevertov
Copy link
Author

Hi,
Tried what @nicoddemus told me to do with the '--pyargs' flag, it did not work.
nicoddemus, I think you misunderstood my problem a little. The tests are collected and tested when I activate pytest using os.system command, but not when using the pytest.main function.
Furthermore, my zip files are added to the PYTHONPATH and work when I add the folder containig them, but I also tried to add them directly and it didn't help.

Sorry it took so much time to report back about the try.

@nicoddemus
Copy link
Member

Hi @jlevertov,

I managed to reproduce your issue I think:

I created two zip files (although only one should be sufficient), then I added the full path to them to PYTHONPATH and I get this output:

ERROR: file or package not found: package_b.tests.test_file (missing __init__.py?)

This happens regardless if I use pytest.main() or os.system (I took care of moving the original directories package_a and package_b to somewhere else so they don't get picked up by accident).

Looking at the code which handles --pyargs it is now clear that it does not work for files inside zip files:

pytest/_pytest/main.py

Lines 793 to 808 in 3bc7ced

def _parsearg(self, arg):
""" return (fspath, names) tuple after checking the file exists. """
parts = str(arg).split("::")
if self.config.option.pyargs:
parts[0] = self._tryconvertpyarg(parts[0])
relpath = parts[0].replace("/", os.sep)
path = self.config.invocation_dir.join(relpath, abs=True)
if not path.check():
if self.config.option.pyargs:
raise UsageError(
"file or package not found: " + arg +
" (missing __init__.py?)")
else:
raise UsageError("file not found: " + arg)
parts[0] = path
return parts

This would require some support in py.path to be able to load paths from inside zip files as well

@nicoddemus
Copy link
Member

This is a duplicate of #1445

@jlevertov
Copy link
Author

jlevertov commented Jan 29, 2018

@nicoddemus

In my case the tests do run for os.system command and when using pytest.main I get a totally different error than what you got:

/usr/local/lib/python2.7/dist-packages/py/_path/local.py:682 in pyimport
   `issame = self.samefile(modfile)`
/usr/local/lib/python2.7/dist-packages/py/_path/local.py:197 in samefile
    `os.path.samefile, self.strpath, other)`
/usr/local/lib/python2.7/dist-packages/py/_error.py:86 in chacked_call
    `raise cls("%s%r" % (func.__name__, args))`
E ENOTDIR: [Not a directory]: samefile('path_to_test_file', 'path_to_test_file_inside_package_b_zip')
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interurupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
============================= 1 error in 0.13 seconds ================================

The packages do have init.py in them, and are found when needed.

@nicoddemus
Copy link
Member

Well I'm on Windows, perhaps it is related to that (although looking at the code I can't really see how). Perhaps you can package a zipfile with all the files required to reproduce your problem? I would be happy to give that a go to see if I can explain the discrepancy between our runs, although pytest doesn't support importing test files from zipfiles at the moment AFAIK.

@jlevertov
Copy link
Author

Thank you for your help, after further analysis, it appears that something in the project was causing this problem, I did a fresh start and everything appears to be working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: needs information reporter needs to provide more information; can be closed after 2 or more weeks of inactivity topic: collection related to the collection phase type: question general question, might be closed after 2 weeks of inactivity
Projects
None yet
Development

No branches or pull requests

4 participants