Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
Bug 951736 - Adjust sys.path while native commands are executed; r=ted
Browse files Browse the repository at this point in the history
The previous behavior only adjusted sys.path during module import. This
caused problems when there were delayed imports.
  • Loading branch information
indygreg committed Dec 18, 2013
1 parent 24825e9 commit 5f68293
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 20 deletions.
39 changes: 19 additions & 20 deletions pymake/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,21 +346,6 @@ def __init__(self, message, exitcode):
def __str__(self):
return self.message

def load_module_recursive(module, path):
"""
Like __import__, but allow passing a custom path to search for modules.
"""
oldsyspath = sys.path
sys.path = []
for p in path:
site.addsitedir(p)
sys.path.extend(oldsyspath)
try:
__import__(module)
except ImportError:
return
finally:
sys.path = oldsyspath

class PythonJob(Job):
"""
Expand All @@ -380,16 +365,28 @@ def run(self):
# os.environ is a magic dictionary. Setting it to something else
# doesn't affect the environment of subprocesses, so use clear/update
oldenv = dict(os.environ)

# sys.path is adjusted for the entire lifetime of the command
# execution. This ensures any delayed imports will still work.
oldsyspath = list(sys.path)
try:
os.chdir(self.cwd)
os.environ.clear()
os.environ.update(self.env)

sys.path = []
for p in sys.path + self.pycommandpath:
site.addsitedir(p)
sys.path.extend(oldsyspath)

if self.module not in sys.modules:
load_module_recursive(self.module,
sys.path + self.pycommandpath)
if self.module not in sys.modules:
print >>sys.stderr, "No module named '%s'" % self.module
return -127
try:
__import__(self.module)
except Exception as e:
print >>sys.stderr, 'Error importing %s: %s' % (
self.module, e)
return -127

m = sys.modules[self.module]
if self.method not in m.__dict__:
print >>sys.stderr, "No method named '%s' in module %s" % (self.method, self.module)
Expand All @@ -415,10 +412,12 @@ def run(self):
finally:
os.environ.clear()
os.environ.update(oldenv)
sys.path = oldsyspath
# multiprocessing exits via os._exit, make sure that all output
# from command gets written out before that happens.
sys.stdout.flush()
sys.stderr.flush()

return 0

def job_runner(job):
Expand Down
12 changes: 12 additions & 0 deletions tests/native-command-delay-load.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#T gmake skip

# This test exists to verify that sys.path is adjusted during command
# execution and that delay importing a module will work.

CMD = %pycmd delayloadfn
PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir

all:
$(CMD)
@echo TEST-PASS

3 changes: 3 additions & 0 deletions tests/pycmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ def asplode_return(args):

def asplode_raise(args):
raise Exception(args[0])

def delayloadfn(args):
import delayload
1 change: 1 addition & 0 deletions tests/subdir/delayload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# This module exists to test delay importing of modules at run-time.

0 comments on commit 5f68293

Please sign in to comment.