From f2278cf2f0297b5223828228311f8ac01c5b36bc Mon Sep 17 00:00:00 2001 From: Kodi Arfer Date: Tue, 20 Jun 2017 16:12:32 -0700 Subject: [PATCH] Support PYTHONDONTWRITEBYTECODE --- NEWS | 1 + hy/importer.py | 15 ++++++++------- tests/test_bin.py | 25 +++++++++++++++++-------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index 1a6c3d5..b99e228 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ Changes from 0.13.0 [ Bug Fixes ] * Numeric literals are no longer parsed as symbols when followed by a dot and a symbol + * Hy now respects the environment variable PYTHONDONTWRITEBYTECODE Changes from 0.12.1 diff --git a/hy/importer.py b/hy/importer.py index 878e1be..ec3b606 100644 --- a/hy/importer.py +++ b/hy/importer.py @@ -96,13 +96,14 @@ def import_file_to_module(module_name, fpath, loader=None): module = imp.new_module(module_name) module.__file__ = fpath code = ast_compile(_ast, fpath, "exec") - try: - write_code_as_pyc(fpath, code) - except (IOError, OSError): - # We failed to save the bytecode, probably because of a - # permissions issue. The user only asked to import the - # file, so don't bug them about it. - pass + if not os.environ.get('PYTHONDONTWRITEBYTECODE'): + try: + write_code_as_pyc(fpath, code) + except (IOError, OSError): + # We failed to save the bytecode, probably because of a + # permissions issue. The user only asked to import the + # file, so don't bug them about it. + pass eval(code, module.__dict__) except (HyTypeError, LexException) as e: if e.source is None: diff --git a/tests/test_bin.py b/tests/test_bin.py index 8383f46..c2e31e9 100644 --- a/tests/test_bin.py +++ b/tests/test_bin.py @@ -19,13 +19,18 @@ def hr(s=""): return "hy --repl-output-fn=hy.contrib.hy-repr.hy-repr " + s -def run_cmd(cmd, stdin_data=None, expect=0): +def run_cmd(cmd, stdin_data=None, expect=0, dontwritebytecode=False): + env = None + if dontwritebytecode: + env = dict(os.environ) + env["PYTHONDONTWRITEBYTECODE"] = "1" p = subprocess.Popen(os.path.join(hy_dir, cmd), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, - shell=True) + shell=True, + env=env) if stdin_data is not None: p.stdin.write(stdin_data) p.stdin.flush() @@ -241,10 +246,11 @@ def test_bin_hy_no_main(): assert "This Should Still Work" in output -@pytest.mark.parametrize('can_byte_compile', [True, False]) +@pytest.mark.parametrize('scenario', [ + "normal", "prevent_by_force", "prevent_by_env"]) @pytest.mark.parametrize('cmd_fmt', [ 'hy {fpath}', 'hy -m {modname}', "hy -c '(import {modname})'"]) -def test_bin_hy_byte_compile(can_byte_compile, cmd_fmt): +def test_bin_hy_byte_compile(scenario, cmd_fmt): modname = "tests.resources.bin.bytecompile" fpath = modname.replace(".", "/") + ".hy" @@ -252,26 +258,29 @@ def test_bin_hy_byte_compile(can_byte_compile, cmd_fmt): rm(get_bytecode_path(fpath)) - if not can_byte_compile: + if scenario == "prevent_by_force": # Keep Hy from being able to byte-compile the module by # creating a directory at the target location. os.mkdir(get_bytecode_path(fpath)) # Whether or not we can byte-compile the module, we should be able # to run it. - output, _ = run_cmd(cmd) + output, _ = run_cmd(cmd, dontwritebytecode=scenario == "prevent_by_env") assert "Hello from macro" in output assert "The macro returned: boink" in output - if can_byte_compile: + if scenario == "normal": # That should've byte-compiled the module. assert os.path.exists(get_bytecode_path(fpath)) + elif scenario == "prevent_by_env": + # No byte-compiled version should've been created. + assert not os.path.exists(get_bytecode_path(fpath)) # When we run the same command again, and we've byte-compiled the # module, the byte-compiled version should be run instead of the # source, in which case the macro shouldn't be run. output, _ = run_cmd(cmd) - assert ("Hello from macro" in output) ^ can_byte_compile + assert ("Hello from macro" in output) ^ (scenario == "normal") assert "The macro returned: boink" in output