diff options
author | Damien George <damien.p.george@gmail.com> | 2015-08-14 12:24:11 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2015-08-17 12:51:26 +0100 |
commit | 65dc960e3b22a8426e369607e47c19b380ce30ea (patch) | |
tree | 5e55ec2861df54e14fdb0eac1d030b34f684743b /tests/bytecode/pylib-tests/runpy.py | |
parent | 0e978349a5e7696aa44a0faf5d046081a0616ca5 (diff) | |
download | micropython-65dc960e3b22a8426e369607e47c19b380ce30ea.tar.gz micropython-65dc960e3b22a8426e369607e47c19b380ce30ea.zip |
unix-cpy: Remove unix-cpy. It's no longer needed.
unix-cpy was originally written to get semantic equivalent with CPython
without writing functional tests. When writing the initial
implementation of uPy it was a long way between lexer and functional
tests, so the half-way test was to make sure that the bytecode was
correct. The idea was that if the uPy bytecode matched CPython 1-1 then
uPy would be proper Python if the bytecodes acted correctly. And having
matching bytecode meant that it was less likely to miss some deep
subtlety in the Python semantics that would require an architectural
change later on.
But that is all history and it no longer makes sense to retain the
ability to output CPython bytecode, because:
1. It outputs CPython 3.3 compatible bytecode. CPython's bytecode
changes from version to version, and seems to have changed quite a bit
in 3.5. There's no point in changing the bytecode output to match
CPython anymore.
2. uPy and CPy do different optimisations to the bytecode which makes it
harder to match.
3. The bytecode tests are not run. They were never part of Travis and
are not run locally anymore.
4. The EMIT_CPYTHON option needs a lot of extra source code which adds
heaps of noise, especially in compile.c.
5. Now that there is an extensive test suite (which tests functionality)
there is no need to match the bytecode. Some very subtle behaviour is
tested with the test suite and passing these tests is a much better
way to stay Python-language compliant, rather than trying to match
CPy bytecode.
Diffstat (limited to 'tests/bytecode/pylib-tests/runpy.py')
-rw-r--r-- | tests/bytecode/pylib-tests/runpy.py | 262 |
1 files changed, 0 insertions, 262 deletions
diff --git a/tests/bytecode/pylib-tests/runpy.py b/tests/bytecode/pylib-tests/runpy.py deleted file mode 100644 index 39c0e9f7dd..0000000000 --- a/tests/bytecode/pylib-tests/runpy.py +++ /dev/null @@ -1,262 +0,0 @@ -"""runpy.py - locating and running Python code using the module namespace - -Provides support for locating and running Python scripts using the Python -module namespace instead of the native filesystem. - -This allows Python code to play nicely with non-filesystem based PEP 302 -importers when locating support scripts as well as when importing modules. -""" -# Written by Nick Coghlan <ncoghlan at gmail.com> -# to implement PEP 338 (Executing Modules as Scripts) - - -import os -import sys -import importlib.machinery # importlib first so we can test #15386 via -m -import imp -from pkgutil import read_code, get_loader, get_importer - -__all__ = [ - "run_module", "run_path", -] - -class _TempModule(object): - """Temporarily replace a module in sys.modules with an empty namespace""" - def __init__(self, mod_name): - self.mod_name = mod_name - self.module = imp.new_module(mod_name) - self._saved_module = [] - - def __enter__(self): - mod_name = self.mod_name - try: - self._saved_module.append(sys.modules[mod_name]) - except KeyError: - pass - sys.modules[mod_name] = self.module - return self - - def __exit__(self, *args): - if self._saved_module: - sys.modules[self.mod_name] = self._saved_module[0] - else: - del sys.modules[self.mod_name] - self._saved_module = [] - -class _ModifiedArgv0(object): - def __init__(self, value): - self.value = value - self._saved_value = self._sentinel = object() - - def __enter__(self): - if self._saved_value is not self._sentinel: - raise RuntimeError("Already preserving saved value") - self._saved_value = sys.argv[0] - sys.argv[0] = self.value - - def __exit__(self, *args): - self.value = self._sentinel - sys.argv[0] = self._saved_value - -def _run_code(code, run_globals, init_globals=None, - mod_name=None, mod_fname=None, - mod_loader=None, pkg_name=None): - """Helper to run code in nominated namespace""" - if init_globals is not None: - run_globals.update(init_globals) - run_globals.update(__name__ = mod_name, - __file__ = mod_fname, - __cached__ = None, - __doc__ = None, - __loader__ = mod_loader, - __package__ = pkg_name) - exec(code, run_globals) - return run_globals - -def _run_module_code(code, init_globals=None, - mod_name=None, mod_fname=None, - mod_loader=None, pkg_name=None): - """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, - mod_name, mod_fname, mod_loader, pkg_name) - # Copy the globals of the temporary module, as they - # may be cleared when the temporary module goes away - return mod_globals.copy() - - -# This helper is needed due to a missing component in the PEP 302 -# loader protocol (specifically, "get_filename" is non-standard) -# Since we can't introduce new features in maintenance releases, -# support was added to zipimporter under the name '_get_filename' -def _get_filename(loader, mod_name): - for attr in ("get_filename", "_get_filename"): - meth = getattr(loader, attr, None) - if meth is not None: - return os.path.abspath(meth(mod_name)) - return None - -# Helper to get the loader, code and filename for a module -def _get_module_details(mod_name): - loader = get_loader(mod_name) - if loader is None: - 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") - try: - pkg_main_name = mod_name + ".__main__" - return _get_module_details(pkg_main_name) - except ImportError as e: - raise ImportError(("%s; %r is a package and cannot " + - "be directly executed") %(e, mod_name)) - code = loader.get_code(mod_name) - if code is None: - raise ImportError("No code object available for %s" % mod_name) - filename = _get_filename(loader, mod_name) - return mod_name, loader, code, filename - -# 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 - - Note that the executed module will have full access to the - __main__ namespace. If this is not desirable, the run_module() - function should be used to run the module code in a fresh namespace. - - At the very least, these variables in __main__ will be overwritten: - __name__ - __file__ - __cached__ - __loader__ - __package__ - """ - try: - if alter_argv or mod_name != "__main__": # i.e. -m switch - mod_name, loader, code, fname = _get_module_details(mod_name) - else: # i.e. directory or zipfile execution - mod_name, loader, code, fname = _get_main_module_details() - except ImportError as 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__' module 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__ - if alter_argv: - sys.argv[0] = fname - return _run_code(code, main_globals, None, - "__main__", fname, loader, pkg_name) - -def run_module(mod_name, init_globals=None, - run_name=None, alter_sys=False): - """Execute a module's code without importing it - - Returns the resulting top level namespace dictionary - """ - mod_name, loader, code, fname = _get_module_details(mod_name) - if run_name is None: - run_name = mod_name - pkg_name = mod_name.rpartition('.')[0] - if alter_sys: - return _run_module_code(code, init_globals, run_name, - fname, loader, pkg_name) - else: - # Leave the sys module alone - 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 - # Also moves the standard __main__ out of the way so that the - # preexisting __loader__ entry doesn't cause issues - main_name = "__main__" - saved_main = sys.modules[main_name] - del sys.modules[main_name] - 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])) from exc - raise - finally: - sys.modules[main_name] = saved_main - - -def _get_code_from_file(run_name, fname): - # Check for a compiled file first - with open(fname, "rb") as f: - code = read_code(f) - if code is None: - # That didn't work, so try it as normal source code - with open(fname, "rb") as f: - code = compile(f.read(), fname, 'exec') - loader = importlib.machinery.SourceFileLoader(run_name, fname) - else: - loader = importlib.machinery.SourcelessFileLoader(run_name, fname) - return code, loader - -def run_path(path_name, init_globals=None, run_name=None): - """Execute code located at the specified filesystem location - - Returns the resulting top level namespace dictionary - - The file path may refer directly to a Python script (i.e. - one that could be directly executed with execfile) or else - it may refer to a zipfile or directory containing a top - level __main__.py script. - """ - if run_name is None: - run_name = "<run_path>" - pkg_name = run_name.rpartition(".")[0] - importer = get_importer(path_name) - if isinstance(importer, (type(None), imp.NullImporter)): - # Not a valid sys.path entry, so run the code directly - # execfile() doesn't help as we want to allow compiled files - code, mod_loader = _get_code_from_file(run_name, path_name) - return _run_module_code(code, init_globals, run_name, path_name, - mod_loader, pkg_name) - else: - # Importer is defined for path, so add it to - # the start of sys.path - sys.path.insert(0, path_name) - try: - # Here's where things are a little different from the run_module - # case. There, we only had to replace the module in sys while the - # code was running and doing so was somewhat optional. Here, we - # have no choice and we have to remove it even while we read the - # code. If we don't do this, a __loader__ attribute in the - # existing __main__ module may prevent location of the new module. - mod_name, loader, code, fname = _get_main_module_details() - with _TempModule(run_name) as temp_module, \ - _ModifiedArgv0(path_name): - mod_globals = temp_module.module.__dict__ - return _run_code(code, mod_globals, init_globals, - run_name, fname, loader, pkg_name).copy() - finally: - try: - sys.path.remove(path_name) - except ValueError: - pass - - -if __name__ == "__main__": - # Run the module specified as the next command line argument - if len(sys.argv) < 2: - print("No module specified for execution", file=sys.stderr) - else: - del sys.argv[0] # Make the requested module sys.argv[0] - _run_module_as_main(sys.argv[0]) |