Skip to content

Types, Modules & Qualified Names

Principles

The project has a need for a bidirectional lookup of types and modules; When the tracer implementation finds an instance that needs logging, it can query the Resolver for a module path and the instance's type's qualified name. Similary, when given strings containing a module path and a type's qualified name, the Resolver is capable of loading the requested type from its file.

API

Retrieving Module Path and Qualified Type Name from a type

The process of type to module & path is performed by querying the given type using the __module__ and __file__, together with sys.modules.

sys.modules can be queried using a type's __module__ attribute. For builtin types, this query delivers "builtins", which is caught as an early-return. Using the [__file__] attribute on the query's result, using the paths specified in the config file, the Resolver can determine by detection of relative paths whether the requested type is from the traced project, the standard library, or from a third-party dependency.

Examples:

>>> resolver.get_module_and_name(ty=int)
(None, 'int')

>>> resolver.get_module_and_name(ty=pathlib.Path)
('pathlib', 'Path')

>>> resolver.get_module_and_name(ty=fractions.Fraction)
('fractions', 'Fraction')

>>> class Outer:
...     class Inner:
...         class EvenMoreInner:
...             ...

>>> r.get_module_and_name(ty=Outer.Inner.EvenMoreInner)
('__main__', 'Outer.Inner.EvenMoreInner')

Creating a type from a Module Path and Qualified Type Name

The process of module & path to type is facilitated by Python's importlib, which enables dynamic imports from modules.

Examples:

>>> resolver.type_lookup(module_name=None, type_name="int")
<class 'int'>

>>> resolver.type_lookup(module_name="pathlib", type_name="Path")
<class 'pathlib.Path'>

>>> resolver.type_lookup(module_name="fractions", type_name="Fraction")
<class 'fractions.Fraction'>

>>> class Outer:
...     class Inner:
...         class EvenMoreInner:
...             ...

>>> resolver.type_lookup(
...    module_name="__main__", 
...    type_name="Outer.Inner.EvenMoreInner")
<class '__main__.Outer.Inner.EvenMoreInner'>

(The final example doesn't work in the REPL, because the repl cannot be passed as a project path, but tests show that it works in practice)