I'm refactoring a library to use importlib.resources for python 3.7+. I'm using the importlib_resources backport for python 3.6 compatibility. The code works for pythons 3.6-3.8. However, the pytest tests, using pyfakefs, fail for 3.6. Under testing conditions, the path returned from use of importlib_resources is mangled (but under "real-world" conditions they return correctly).
A minimal example: I have the following library structure:
mypackage
├── mypackage
│ ├── __init__.py
│ ├── bin
│ │ └── __init__.py
│ └── find_bin.py
└── tests
└── test_find_bin.py
In the actual library, the bin folder holds binaries (plus an empty __init__
). Code elsewhere in the library needs a path to it. find_bin.py
demonstrates a function that will return the path:
import sys
if sys.version_info >= (3, 7):
from importlib import resources
else:
import importlib_resources as resources
import mypackage.bin
def find_bin():
init_path_context = resources.path(mypackage.bin, '__init__.py')
with init_path_context as p:
init_path = p
bin_path = init_path.parent
return bin_path
The pytest test test_find_bin.py
:
import pathlib
from mypackage.find_bin import find_bin
def test_findbin(fs):
test_bin = (pathlib.Path(__file__)
.resolve()
.parent.parent
.joinpath('mypackage', 'bin'))
print('test bin is ', test_bin)
expected_bin = find_bin()
print('expected bin is ', expected_bin)
assert not expected_bin.exists()
print('test creating fakefs ', test_bin)
fs.create_dir(test_bin)
assert expected_bin.exists()
Python 3.7+ work as expected with the tests. In python 3.6, the expected_bin path is mangled:
test bin is /Users/geoffreysametz/Documents/mypackage/mypackage/bin # correct
expected bin is /var/folders/bv/m5cg5cp15t38sh8rxx244hp00000gn/T # ?!?!?!
I tried to trace through the execution of the find_bin function, and it's long and convoluted. However, I saw that importlib_resources
makes use of python's FakeFilesystem class. My hypothesis is that the problem arises from both importlib_resources
and pytest using fake file systems at the same time.
Is my hypothesis correct? Is there a workaround to getting pytest to test code that uses importlib_resources?