diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/code.py | 5 | ||||
-rwxr-xr-x | Lib/mailbox.py | 28 | ||||
-rw-r--r-- | Lib/os.py | 8 | ||||
-rw-r--r-- | Lib/runpy.py | 58 | ||||
-rw-r--r-- | Lib/test/test_grammar.py | 8 | ||||
-rw-r--r-- | Lib/test/test_runpy.py | 37 |
6 files changed, 97 insertions, 47 deletions
diff --git a/Lib/code.py b/Lib/code.py index 8962927..605aede 100644 --- a/Lib/code.py +++ b/Lib/code.py @@ -287,6 +287,5 @@ def interact(banner=None, readfunc=None, local=None): console.interact(banner) -if __name__ == '__main__': - import pdb - pdb.run("interact()\n") +if __name__ == "__main__": + interact() diff --git a/Lib/mailbox.py b/Lib/mailbox.py index d9c289b..3f299a8 100755 --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -469,12 +469,21 @@ class Maildir(Mailbox): def _refresh(self): """Update table of contents mapping.""" - new_mtime = os.path.getmtime(os.path.join(self._path, 'new')) - cur_mtime = os.path.getmtime(os.path.join(self._path, 'cur')) + if self._last_read is not None: + for subdir in ('new', 'cur'): + mtime = os.path.getmtime(os.path.join(self._path, subdir)) + if mtime > self._last_read: + break + else: + return - if (self._last_read is not None and - new_mtime <= self._last_read and cur_mtime <= self._last_read): - return + # We record the current time - 1sec so that, if _refresh() is called + # again in the same second, we will always re-read the mailbox + # just in case it's been modified. (os.path.mtime() only has + # 1sec resolution.) This results in a few unnecessary re-reads + # when _refresh() is called multiple times in the same second, + # but once the clock ticks over, we will only re-read as needed. + now = time.time() - 1 self._toc = {} def update_dir (subdir): @@ -489,14 +498,7 @@ class Maildir(Mailbox): update_dir('new') update_dir('cur') - # We record the current time - 1sec so that, if _refresh() is called - # again in the same second, we will always re-read the mailbox - # just in case it's been modified. (os.path.mtime() only has - # 1sec resolution.) This results in a few unnecessary re-reads - # when _refresh() is called multiple times in the same second, - # but once the clock ticks over, we will only re-read as needed. - now = int(time.time() - 1) - self._last_read = time.time() - 1 + self._last_read = now def _lookup(self, key): """Use TOC to return subpath for given key, or raise a KeyError.""" @@ -249,7 +249,7 @@ def walk(top, topdown=True, onerror=None, followlinks=False): dirs.remove('CVS') # don't visit CVS directories """ - from os.path import join, isdir, islink + islink, join, isdir = path.islink, path.join, path.isdir # We may not have read permission for top, in which case we can't # get a list of the files the directory contains. os.walk @@ -275,9 +275,9 @@ def walk(top, topdown=True, onerror=None, followlinks=False): if topdown: yield top, dirs, nondirs for name in dirs: - path = join(top, name) - if followlinks or not islink(path): - for x in walk(path, topdown, onerror, followlinks): + new_path = join(top, name) + if followlinks or not islink(new_path): + for x in walk(new_path, topdown, onerror, followlinks): yield x if not topdown: yield top, dirs, nondirs diff --git a/Lib/runpy.py b/Lib/runpy.py index e277de3..9fe431a 100644 --- a/Lib/runpy.py +++ b/Lib/runpy.py @@ -62,7 +62,7 @@ class _ModifiedArgv0(object): def _run_code(code, run_globals, init_globals=None, mod_name=None, mod_fname=None, mod_loader=None, pkg_name=None): - """Helper for _run_module_code""" + """Helper to run code in nominated namespace""" if init_globals is not None: run_globals.update(init_globals) run_globals.update(__name__ = mod_name, @@ -75,7 +75,7 @@ def _run_code(code, run_globals, init_globals=None, def _run_module_code(code, init_globals=None, mod_name=None, mod_fname=None, mod_loader=None, pkg_name=None): - """Helper for run_module""" + """Helper to run code in new namespace with sys modified""" with _TempModule(mod_name) as temp_module, _ModifiedArgv0(mod_fname): mod_globals = temp_module.module.__dict__ _run_code(code, mod_globals, init_globals, @@ -103,7 +103,7 @@ def _get_module_details(mod_name): raise ImportError("No module named %s" % mod_name) if loader.is_package(mod_name): if mod_name == "__main__" or mod_name.endswith(".__main__"): - raise ImportError(("Cannot use package as __main__ module")) + raise ImportError("Cannot use package as __main__ module") try: pkg_main_name = mod_name + ".__main__" return _get_module_details(pkg_main_name) @@ -116,29 +116,22 @@ def _get_module_details(mod_name): filename = _get_filename(loader, mod_name) return mod_name, loader, code, filename - -def _get_main_module_details(): - # Helper that gives a nicer error message when attempting to - # execute a zipfile or directory by invoking __main__.py - main_name = "__main__" - try: - return _get_module_details(main_name) - except ImportError as exc: - if main_name in str(exc): - raise ImportError("can't find %r module in %r" % - (main_name, sys.path[0])) - raise - -# This function is the actual implementation of the -m switch and direct -# execution of zipfiles and directories and is deliberately kept private. -# This avoids a repeat of the situation where run_module() no longer met the -# needs of mainmodule.c, but couldn't be changed because it was public +# XXX ncoghlan: Should this be documented and made public? +# (Current thoughts: don't repeat the mistake that lead to its +# creation when run_module() no longer met the needs of +# mainmodule.c, but couldn't be changed because it was public) def _run_module_as_main(mod_name, alter_argv=True): """Runs the designated module in the __main__ namespace - These __*__ magic variables will be overwritten: + Note that the executed module will have full access to the + __main__ namespace. If this is not desirable, the run_module() + function sbould be used to run the module code in a fresh namespace. + + At the very least, these variables in __main__ will be overwritten: + __name__ __file__ __loader__ + __package__ """ try: if alter_argv or mod_name != "__main__": # i.e. -m switch @@ -146,7 +139,16 @@ def _run_module_as_main(mod_name, alter_argv=True): else: # i.e. directory or zipfile execution mod_name, loader, code, fname = _get_main_module_details() except ImportError as exc: - msg = "%s: %s" % (sys.executable, str(exc)) + # Try to provide a good error message + # for directories, zip files and the -m switch + if alter_argv: + # For -m switch, just display the exception + info = str(exc) + else: + # For directories/zipfiles, let the user + # know what the code was looking for + info = "can't find '__main__.py' in %r" % sys.argv[0] + msg = "%s: %s" % (sys.executable, info) sys.exit(msg) pkg_name = mod_name.rpartition('.')[0] main_globals = sys.modules["__main__"].__dict__ @@ -173,6 +175,18 @@ def run_module(mod_name, init_globals=None, return _run_code(code, {}, init_globals, run_name, fname, loader, pkg_name) +def _get_main_module_details(): + # Helper that gives a nicer error message when attempting to + # execute a zipfile or directory by invoking __main__.py + main_name = "__main__" + try: + return _get_module_details(main_name) + except ImportError as exc: + if main_name in str(exc): + raise ImportError("can't find %r module in %r" % + (main_name, sys.path[0])) + raise + # XXX (ncoghlan): Perhaps expose the C API function # as imp.get_importer instead of reimplementing it in Python? diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index b861207..4ef4969 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -915,6 +915,14 @@ class GrammarTests(unittest.TestCase): self.assertEqual((6 / 2 if 1 else 3), 3) self.assertEqual((6 < 4 if 0 else 2), 2) + def test_paren_evaluation(self): + self.assertEqual(16 // (4 // 2), 8) + self.assertEqual((16 // 4) // 2, 2) + self.assertEqual(16 // 4 // 2, 2) + self.assertTrue(False is (2 is 3)) + self.assertFalse((False is 2) is 3) + self.assertFalse(False is 2 is 3) + def test_main(): run_unittest(TokenTests, GrammarTests) diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py index 88e05fe..0542194 100644 --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -100,8 +100,8 @@ class RunModuleTest(unittest.TestCase): self.expect_import_error("a.bee") self.expect_import_error(".howard") self.expect_import_error("..eaten") - # Package - self.expect_import_error("logging") + # Package without __main__.py + self.expect_import_error("multiprocessing") def test_library_module(self): run_module("runpy") @@ -113,9 +113,9 @@ class RunModuleTest(unittest.TestCase): pkg_file.close() return pkg_fname - def _make_pkg(self, source, depth): + def _make_pkg(self, source, depth, mod_base="runpy_test"): pkg_name = "__runpy_pkg__" - test_fname = "runpy_test.py" + test_fname = mod_base+os.extsep+"py" pkg_dir = sub_dir = tempfile.mkdtemp() if verbose: print(" Package tree in:", sub_dir) sys.path.insert(0, pkg_dir) @@ -130,7 +130,7 @@ class RunModuleTest(unittest.TestCase): mod_file.write(source) mod_file.close() if verbose: print(" Created:", mod_fname) - mod_name = (pkg_name+".")*depth + "runpy_test" + mod_name = (pkg_name+".")*depth + mod_base return pkg_dir, mod_fname, mod_name def _del_pkg(self, top, depth, mod_name): @@ -179,6 +179,28 @@ class RunModuleTest(unittest.TestCase): self._del_pkg(pkg_dir, depth, mod_name) if verbose: print("Module executed successfully") + def _check_package(self, depth): + pkg_dir, mod_fname, mod_name = ( + self._make_pkg("x=1\n", depth, "__main__")) + pkg_name, _, _ = mod_name.rpartition(".") + forget(mod_name) + try: + if verbose: print("Running from source:", pkg_name) + d1 = run_module(pkg_name) # Read from source + self.assertTrue("x" in d1) + self.assertTrue(d1["x"] == 1) + del d1 # Ensure __loader__ entry doesn't keep file open + __import__(mod_name) + os.remove(mod_fname) + if verbose: print("Running from compiled:", pkg_name) + d2 = run_module(pkg_name) # Read from bytecode + self.assertTrue("x" in d2) + self.assertTrue(d2["x"] == 1) + del d2 # Ensure __loader__ entry doesn't keep file open + finally: + self._del_pkg(pkg_dir, depth, pkg_name) + if verbose: print("Package executed successfully") + def _add_relative_modules(self, base_dir, source, depth): if depth <= 1: raise ValueError("Relative module test needs depth > 1") @@ -240,6 +262,11 @@ from ..uncle.cousin import nephew if verbose: print("Testing package depth:", depth) self._check_module(depth) + def test_run_package(self): + for depth in range(1, 4): + if verbose: print("Testing package depth:", depth) + self._check_package(depth) + def test_explicit_relative_import(self): for depth in range(2, 5): if verbose: print("Testing relative imports at depth:", depth) |