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

Reply via email to