Merge pull request #1309 from Kodiologist/pythondontwritebytecode

Support PYTHONDONTWRITEBYTECODE
This commit is contained in:
gilch 2017-06-26 19:46:36 -06:00 committed by GitHub
commit 2e465dbf70
3 changed files with 45 additions and 34 deletions

1
NEWS
View File

@ -8,6 +8,7 @@ Changes from 0.13.0
[ Bug Fixes ] [ Bug Fixes ]
* Numeric literals are no longer parsed as symbols when followed by a dot * Numeric literals are no longer parsed as symbols when followed by a dot
and a symbol and a symbol
* Hy now respects the environment variable PYTHONDONTWRITEBYTECODE
Changes from 0.12.1 Changes from 0.12.1

View File

@ -96,13 +96,14 @@ def import_file_to_module(module_name, fpath, loader=None):
module = imp.new_module(module_name) module = imp.new_module(module_name)
module.__file__ = fpath module.__file__ = fpath
code = ast_compile(_ast, fpath, "exec") code = ast_compile(_ast, fpath, "exec")
try: if not os.environ.get('PYTHONDONTWRITEBYTECODE'):
write_code_as_pyc(fpath, code) try:
except (IOError, OSError): write_code_as_pyc(fpath, code)
# We failed to save the bytecode, probably because of a except (IOError, OSError):
# permissions issue. The user only asked to import the # We failed to save the bytecode, probably because of a
# file, so don't bug them about it. # permissions issue. The user only asked to import the
pass # file, so don't bug them about it.
pass
eval(code, module.__dict__) eval(code, module.__dict__)
except (HyTypeError, LexException) as e: except (HyTypeError, LexException) as e:
if e.source is None: if e.source is None:

View File

@ -9,6 +9,7 @@ import subprocess
import re import re
from hy._compat import PY3 from hy._compat import PY3
from hy.importer import get_bytecode_path from hy.importer import get_bytecode_path
import pytest
hy_dir = os.environ.get('HY_DIR', '') hy_dir = os.environ.get('HY_DIR', '')
@ -18,13 +19,18 @@ def hr(s=""):
return "hy --repl-output-fn=hy.contrib.hy-repr.hy-repr " + 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), p = subprocess.Popen(os.path.join(hy_dir, cmd),
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
universal_newlines=True, universal_newlines=True,
shell=True) shell=True,
env=env)
if stdin_data is not None: if stdin_data is not None:
p.stdin.write(stdin_data) p.stdin.write(stdin_data)
p.stdin.flush() p.stdin.flush()
@ -240,39 +246,42 @@ def test_bin_hy_no_main():
assert "This Should Still Work" in output assert "This Should Still Work" in output
def test_bin_hy_byte_compile(): @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(scenario, cmd_fmt):
modname = "tests.resources.bin.bytecompile" modname = "tests.resources.bin.bytecompile"
fpath = modname.replace(".", "/") + ".hy" fpath = modname.replace(".", "/") + ".hy"
cmd = cmd_fmt.format(**locals())
for can_byte_compile in [True, False]: rm(get_bytecode_path(fpath))
for cmd in ["hy " + fpath,
"hy -m " + modname,
"hy -c '(import {})'".format(modname)]:
rm(get_bytecode_path(fpath)) 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))
if not can_byte_compile: # Whether or not we can byte-compile the module, we should be able
# Keep Hy from being able to byte-compile the module by # to run it.
# creating a directory at the target location. output, _ = run_cmd(cmd, dontwritebytecode=scenario == "prevent_by_env")
os.mkdir(get_bytecode_path(fpath)) assert "Hello from macro" in output
assert "The macro returned: boink" in output
# Whether or not we can byte-compile the module, we should be able if scenario == "normal":
# to run it. # That should've byte-compiled the module.
output, _ = run_cmd(cmd) assert os.path.exists(get_bytecode_path(fpath))
assert "Hello from macro" in output elif scenario == "prevent_by_env":
assert "The macro returned: boink" in output # No byte-compiled version should've been created.
assert not os.path.exists(get_bytecode_path(fpath))
if can_byte_compile: # When we run the same command again, and we've byte-compiled the
# That should've byte-compiled the module. # module, the byte-compiled version should be run instead of the
assert os.path.exists(get_bytecode_path(fpath)) # source, in which case the macro shouldn't be run.
output, _ = run_cmd(cmd)
# When we run the same command again, and we've byte-compiled the assert ("Hello from macro" in output) ^ (scenario == "normal")
# module, the byte-compiled version should be run instead of the assert "The macro returned: boink" in output
# source, in which case the macro shouldn't be run.
output, _ = run_cmd(cmd)
assert ("Hello from macro" in output) ^ can_byte_compile
assert "The macro returned: boink" in output
def test_bin_hy_module_main(): def test_bin_hy_module_main():