Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a test to avoid regression in the alias handling #588

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
66 changes: 66 additions & 0 deletions pydoctor/test/test_astbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -1974,6 +1974,72 @@ class j: pass
assert system.allobjects['_impl2'].resolveName('i') == system.allobjects['top'].contents['i']
assert all(n in system.allobjects['top'].contents for n in ['f', 'g', 'h', 'i', 'j'])

@systemcls_param
def test_module_level_attributes_and_aliases(systemcls: Type[model.System]) -> None:
"""
Currently, the first analyzed assigment wins, basically. I believe further logic should be added
such that definitions in the orelse clause (that we currently doesn't visit at all) of the Try node is processed before the
except handlers. This way could define our aliases both there and in the body of the
Try node and fall back to what's defnied in the handlers if the names doesn't exist yet.
"""
system = systemcls()
builder = system.systemBuilder(system)
builder.addModuleString('''
ssl = 1
''', modname='twisted.internet')
builder.addModuleString('''
try:
from twisted.internet import ssl as _ssl
# The first analyzed assigment to an alias wins.
ssl = _ssl
# For classic variables, the rules are the same.
var = 1
# For constants, the rules are still the same.
VAR = 1
# Looks like a constant, but should be treated like an alias
ALIAS = _ssl
except ImportError:
ssl = None
var = 2
VAR = 2
ALIAS = None
''', modname='mod')
builder.buildModules()
mod = system.allobjects['mod']

# Test alias
assert mod.expandName('ssl')=="twisted.internet.ssl"
assert mod.expandName('_ssl')=="twisted.internet.ssl"
s = mod.resolveName('ssl')
assert isinstance(s, model.Attribute)
assert s.value is not None
assert ast.literal_eval(s.value)==1
assert s.kind == model.DocumentableKind.VARIABLE

# Test variable
assert mod.expandName('var')=="mod.var"
v = mod.resolveName('var')
assert isinstance(v, model.Attribute)
assert v.value is not None
assert ast.literal_eval(v.value)==1
assert v.kind == model.DocumentableKind.VARIABLE

# Test constant
assert mod.expandName('VAR')=="mod.VAR"
V = mod.resolveName('VAR')
assert isinstance(V, model.Attribute)
assert V.value is not None
assert ast.literal_eval(V.value)==1
assert V.kind == model.DocumentableKind.CONSTANT

# Test looks like constant but actually an alias.
assert mod.expandName('ALIAS')=="twisted.internet.ssl"
s = mod.resolveName('ALIAS')
assert isinstance(s, model.Attribute)
assert s.value is not None
assert ast.literal_eval(s.value)==1
assert s.kind == model.DocumentableKind.VARIABLE

@systemcls_param
def test_exception_kind(systemcls: Type[model.System], capsys: CapSys) -> None:
"""
Expand Down