Add module reloading tests

This commit is contained in:
Brandon T. Willard 2018-08-20 10:27:31 -05:00
parent 87a5b117a1
commit e9e7171b56

View File

@ -3,10 +3,12 @@
# license. See the LICENSE. # license. See the LICENSE.
import os import os
import sys
import ast import ast
import imp
import tempfile import tempfile
import importlib
import runpy import runpy
import importlib
from fractions import Fraction from fractions import Fraction
@ -14,6 +16,7 @@ import pytest
import hy import hy
from hy.errors import HyTypeError from hy.errors import HyTypeError
from hy.lex import LexException
from hy.compiler import hy_compile from hy.compiler import hy_compile
from hy.importer import hy_parse, HyLoader, cache_from_source from hy.importer import hy_parse, HyLoader, cache_from_source
@ -98,3 +101,100 @@ def test_eval():
'(if True "this is if true" "this is if false")') == "this is if true" '(if True "this is if true" "this is if false")') == "this is if true"
assert eval_str('(lfor num (range 100) :if (= (% num 2) 1) (pow num 2))') == [ assert eval_str('(lfor num (range 100) :if (= (% num 2) 1) (pow num 2))') == [
pow(num, 2) for num in range(100) if num % 2 == 1] pow(num, 2) for num in range(100) if num % 2 == 1]
def test_reload():
"""Copied from CPython's `test_import.py`"""
def unlink(filename):
os.unlink(source)
bytecode = cache_from_source(source)
if os.path.isfile(bytecode):
os.unlink(bytecode)
TESTFN = 'testfn'
source = TESTFN + os.extsep + "hy"
with open(source, "w") as f:
f.write("(setv a 1)")
f.write("(setv b 2)")
sys.path.insert(0, os.curdir)
try:
mod = importlib.import_module(TESTFN)
assert TESTFN in sys.modules
assert mod.a == 1
assert mod.b == 2
# On WinXP, just replacing the .py file wasn't enough to
# convince reload() to reparse it. Maybe the timestamp didn't
# move enough. We force it to get reparsed by removing the
# compiled file too.
unlink(source)
# Now damage the module.
with open(source, "w") as f:
f.write("(setv a 10)")
f.write("(setv b (// 20 0))")
with pytest.raises(ZeroDivisionError):
imp.reload(mod)
# But we still expect the module to be in sys.modules.
mod = sys.modules.get(TESTFN)
assert mod is not None
# We should have replaced a w/ 10, but the old b value should
# stick.
assert mod.a == 10
assert mod.b == 2
# Now fix the issue and reload the module.
unlink(source)
with open(source, "w") as f:
f.write("(setv a 11)")
f.write("(setv b (// 20 1))")
imp.reload(mod)
mod = sys.modules.get(TESTFN)
assert mod is not None
assert mod.a == 11
assert mod.b == 20
# Now cause a LexException
unlink(source)
with open(source, "w") as f:
f.write("(setv a 11")
f.write("(setv b (// 20 1))")
with pytest.raises(LexException):
imp.reload(mod)
mod = sys.modules.get(TESTFN)
assert mod is not None
assert mod.a == 11
assert mod.b == 20
# Fix it and retry
unlink(source)
with open(source, "w") as f:
f.write("(setv a 12)")
f.write("(setv b (// 10 1))")
imp.reload(mod)
mod = sys.modules.get(TESTFN)
assert mod is not None
assert mod.a == 12
assert mod.b == 10
finally:
del sys.path[0]
unlink(source)
del sys.modules[TESTFN]