From 6f2e374496b7f893ec5678ff3940addf49eb75c5 Mon Sep 17 00:00:00 2001 From: tristanlatr Date: Mon, 23 May 2022 16:06:27 -0400 Subject: [PATCH 1/2] Add a test --- pydoctor/test/test_astbuilder.py | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/pydoctor/test/test_astbuilder.py b/pydoctor/test/test_astbuilder.py index c2f219206..d3593ec7c 100644 --- a/pydoctor/test/test_astbuilder.py +++ b/pydoctor/test/test_astbuilder.py @@ -2075,3 +2075,70 @@ class j: pass assert system.allobjects['top._impl'].resolveName('f') == system.allobjects['top'].contents['f'] 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 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 + From 6ad7123a8d2fc9e9357c7127133fbbbb569de5ca Mon Sep 17 00:00:00 2001 From: tristanlatr <19967168+tristanlatr@users.noreply.github.com> Date: Mon, 23 May 2022 16:35:40 -0400 Subject: [PATCH 2/2] Update pydoctor/test/test_astbuilder.py --- pydoctor/test/test_astbuilder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydoctor/test/test_astbuilder.py b/pydoctor/test/test_astbuilder.py index d3593ec7c..df8e65260 100644 --- a/pydoctor/test/test_astbuilder.py +++ b/pydoctor/test/test_astbuilder.py @@ -2080,7 +2080,7 @@ class j: pass 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 of the Try node is processed before the + 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. """