only try to create the __pycache__ dir (not a tree to it) fixes #60
Also, improve error handling surrounding __pycache__ creation.
This commit is contained in:
parent
f86c8469f5
commit
643ab120f4
|
@ -1,6 +1,7 @@
|
|||
Changes between 2.1.0 and 2.1.1.DEV
|
||||
----------------------------------------------
|
||||
|
||||
- fix error conditions involving the creation of __pycache__
|
||||
- fix assertion rewriting on inserts involving strings containing '%'
|
||||
- fix assertion rewriting on calls with a ** arg
|
||||
- don't cache rewritten modules if bytecode generation is disabled
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import ast
|
||||
import collections
|
||||
import errno
|
||||
import itertools
|
||||
import imp
|
||||
import marshal
|
||||
|
@ -97,15 +98,23 @@ class AssertionRewritingHook(object):
|
|||
cache_dir = os.path.join(fn_pypath.dirname, "__pycache__")
|
||||
if write:
|
||||
try:
|
||||
py.path.local(cache_dir).ensure(dir=True)
|
||||
except py.error.EACCES:
|
||||
state.trace("read only directory: %r" % (fn_pypath.dirname,))
|
||||
write = False
|
||||
except py.error.EEXIST:
|
||||
state.trace("failure to create directory: %r" % (
|
||||
fn_pypath.dirname,))
|
||||
raise
|
||||
#write = False
|
||||
os.mkdir(cache_dir)
|
||||
except OSError:
|
||||
e = sys.exc_info()[1].errno
|
||||
if e == errno.EEXIST:
|
||||
# Either the __pycache__ directory already exists (the
|
||||
# common case) or it's blocked by a non-dir node. In the
|
||||
# latter case, we'll ignore it in _write_pyc.
|
||||
pass
|
||||
elif e == errno.ENOTDIR:
|
||||
# One of the path components was not a directory, likely
|
||||
# because we're in a zip file.
|
||||
write = False
|
||||
elif e == errno.EACCES:
|
||||
state.trace("read only directory: %r" % (fn_pypath.dirname,))
|
||||
write = False
|
||||
else:
|
||||
raise
|
||||
cache_name = fn_pypath.basename[:-3] + "." + PYTEST_TAG + ".pyc"
|
||||
pyc = os.path.join(cache_dir, cache_name)
|
||||
# Notice that even if we're in a read-only directory, I'm going to check
|
||||
|
@ -146,13 +155,21 @@ def _write_pyc(co, source_path, pyc):
|
|||
# little reason deviate, and I hope sometime to be able to use
|
||||
# imp.load_compiled to load them. (See the comment in load_module above.)
|
||||
mtime = int(source_path.mtime())
|
||||
fp = open(pyc, "wb")
|
||||
try:
|
||||
fp = open(pyc, "wb")
|
||||
except IOError:
|
||||
if sys.exc_info()[1].errno == errno.ENOTDIR:
|
||||
# This happens when we get a EEXIST in find_module creating the
|
||||
# __pycache__ directory and __pycache__ is by some non-dir node.
|
||||
return False
|
||||
raise
|
||||
try:
|
||||
fp.write(imp.get_magic())
|
||||
fp.write(struct.pack("<l", mtime))
|
||||
marshal.dump(co, fp)
|
||||
finally:
|
||||
fp.close()
|
||||
return True
|
||||
|
||||
def _rewrite_test(state, fn):
|
||||
"""Try to read and rewrite *fn* and return the code object."""
|
||||
|
@ -186,8 +203,8 @@ def _make_rewritten_pyc(state, fn, pyc, co):
|
|||
# When not on windows, assume rename is atomic. Dump the code object
|
||||
# into a file specific to this process and atomically replace it.
|
||||
proc_pyc = pyc + "." + str(os.getpid())
|
||||
_write_pyc(co, fn, proc_pyc)
|
||||
os.rename(proc_pyc, pyc)
|
||||
if _write_pyc(co, fn, proc_pyc):
|
||||
os.rename(proc_pyc, pyc)
|
||||
return co
|
||||
|
||||
def _read_pyc(source, pyc):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import sys
|
||||
import zipfile
|
||||
import py
|
||||
import pytest
|
||||
|
||||
|
@ -283,6 +284,29 @@ class TestAssertionRewrite:
|
|||
|
||||
class TestRewriteOnImport:
|
||||
|
||||
def test_pycache_is_a_file(self, testdir):
|
||||
testdir.tmpdir.join("__pycache__").write("Hello")
|
||||
testdir.makepyfile("""
|
||||
def test_rewritten():
|
||||
assert "@py_builtins" in globals()""")
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
def test_zipfile(self, testdir):
|
||||
z = testdir.tmpdir.join("myzip.zip")
|
||||
z_fn = str(z)
|
||||
f = zipfile.ZipFile(z_fn, "w")
|
||||
try:
|
||||
f.writestr("test_gum/__init__.py", "")
|
||||
f.writestr("test_gum/test_lizard.py", "")
|
||||
finally:
|
||||
f.close()
|
||||
z.chmod(256)
|
||||
testdir.makepyfile("""
|
||||
import sys
|
||||
sys.path.append(%r)
|
||||
import test_gum.test_lizard""" % (z_fn,))
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
def test_readonly(self, testdir):
|
||||
sub = testdir.mkdir("testing")
|
||||
sub.join("test_readonly.py").write(
|
||||
|
|
Loading…
Reference in New Issue