Xqt has submitted this change and it was merged. Change subject: Updated pwb.py to better mirror direct script runs ......................................................................
Updated pwb.py to better mirror direct script runs Before, execfile() ran the script in environment that pwb.py has, which included os and path imports, and several other variables. This commit uses run_python_file from Ned Batchelors' coverage.py [1], available under the BSD license [2]. See also his blog posts on the subject [3,4]. This commit also adds a test that shells out to compare the locals() for runs through pwb.py as well as to a script directly. After this change, the effects of changeset 76484 can be seen using pwb.py [1] https://bitbucket.org/ned/coveragepy/src/b5abcee50dbe/coverage/execfile.py [2] https://bitbucket.org/ned/coveragepy/src/2c5fb3a8b81cc56d8ad57dd1bd83ef7740f0d65d/setup.py?at=default [3] http://nedbatchelder.com/blog/200904/running_a_python_file_as_main.html [4] http://nedbatchelder.com/blog/200905/running_a_python_file_as_main_take_2.html Change-Id: If9458fca50f07f08441dbb6e06f78bdbae2065de --- M pwb.py A tests/pwb/print_locals.py A tests/pwb_tests.py 3 files changed, 89 insertions(+), 13 deletions(-) Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified diff --git a/pwb.py b/pwb.py index ae732ed..94fef0c 100644 --- a/pwb.py +++ b/pwb.py @@ -12,8 +12,50 @@ # Distributed under the terms of the MIT license. # -import sys + +# The following snippet was developed by Ned Batchelder (and others) +# for coverage.py [1], and is available under the BSD license (see [2]) +# [1] https://bitbucket.org/ned/coveragepy/src/b5abcee50dbe/coverage/execfile.py +# [2] https://bitbucket.org/ned/coveragepy/src/2c5fb3a8b81cc56d8ad57dd1bd83ef7740f0d65d/setup.py?at=default#cl-31 + +import imp import os +import sys + + +def run_python_file(filename, args): + """Run a python file as if it were the main program on the command line. + + `filename` is the path to the file to execute, it need not be a .py file. + `args` is the argument array to present as sys.argv, including the first + element representing the file being executed. + + """ + # Create a module to serve as __main__ + old_main_mod = sys.modules['__main__'] + main_mod = imp.new_module('__main__') + sys.modules['__main__'] = main_mod + main_mod.__file__ = filename + main_mod.__builtins__ = sys.modules['__builtin__'] + + # Set sys.argv and the first path element properly. + old_argv = sys.argv + old_path0 = sys.path[0] + sys.argv = args + sys.path[0] = os.path.dirname(filename) + + try: + source = open(filename).read() + exec compile(source, filename, "exec") in main_mod.__dict__ + finally: + # Restore the old __main__ + sys.modules['__main__'] = old_main_mod + + # Restore the old argv and path + sys.argv = old_argv + sys.path[0] = old_path0 + +#### end of snippet if sys.version_info[0] != 2: raise RuntimeError("ERROR: Pywikipediabot only runs under Python 2") @@ -33,21 +75,20 @@ os.environ["PYWIKIBOT2_DIR"] = os.path.split(__file__)[0] if not os.path.exists(os.path.join(os.environ["PYWIKIBOT2_DIR"], "user-config.py")): - execfile('generate_user_files.py') + run_python_file('generate_user_files.py', ['generate_user_files.py']) -sys.argv.pop(0) -if len(sys.argv) > 0: - if not os.path.exists(sys.argv[0]): - testpath = os.path.join(os.path.split(__file__)[0], 'scripts', sys.argv[0]) +if len(sys.argv) > 1: + fn = sys.argv[1] + args = sys.argv[1:] + + if not os.path.exists(fn): + testpath = os.path.join(os.path.split(__file__)[0], 'scripts', fn) if os.path.exists(testpath): - sys.argv[0] = testpath + fn = testpath else: testpath = testpath + '.py' if os.path.exists(testpath): - sys.argv[0] = testpath + fn = testpath else: - raise Exception("%s not found!" % sys.argv[0]) - sys.path.append(os.path.split(sys.argv[0])[0]) - execfile(sys.argv[0]) -else: - sys.argv.append('') + raise Exception("%s not found!" % fn) + run_python_file(fn, args) diff --git a/tests/pwb/print_locals.py b/tests/pwb/print_locals.py new file mode 100644 index 0000000..1b84ac0 --- /dev/null +++ b/tests/pwb/print_locals.py @@ -0,0 +1,4 @@ +"""docstring""" + +for k,v in locals().copy().iteritems(): + print repr(k), ":", repr(v) diff --git a/tests/pwb_tests.py b/tests/pwb_tests.py new file mode 100644 index 0000000..4cb9759 --- /dev/null +++ b/tests/pwb_tests.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# +# (C) Pywikipedia bot team, 2007 +# +# Distributed under the terms of the MIT license. +# +__version__ = '$Id$' + +import os +import sys +import subprocess + +import unittest + +pypath = sys.executable +basepath = os.path.split(os.path.split(__file__)[0])[0] +pwbpath = os.path.join(basepath, 'pwb.py') +testbasepath = os.path.join(basepath, 'tests', 'pwb') + +class TestPwb(unittest.TestCase): + def testScriptEnvironment(self): + """Make sure the environment is not contaminated, and is the same as + the environment we get when directly running a script.""" + test = os.path.join(testbasepath, 'print_locals.py') + + direct = subprocess.check_output([pypath, test]) + vpwb = subprocess.check_output([pypath, pwbpath, test]) + self.assertEqual(direct, vpwb) + +if __name__=="__main__": + unittest.main(verbosity=10) -- To view, visit https://gerrit.wikimedia.org/r/76486 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: If9458fca50f07f08441dbb6e06f78bdbae2065de Gerrit-PatchSet: 6 Gerrit-Project: pywikibot/core Gerrit-Branch: master Gerrit-Owner: Merlijn van Deen <[email protected]> Gerrit-Reviewer: DrTrigon <[email protected]> Gerrit-Reviewer: Ladsgroup <[email protected]> Gerrit-Reviewer: Legoktm <[email protected]> Gerrit-Reviewer: Merlijn van Deen <[email protected]> Gerrit-Reviewer: Xqt <[email protected]> Gerrit-Reviewer: jenkins-bot _______________________________________________ Pywikibot-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/pywikibot-commits
