Module that provides the module tree node
This class will load the module identified by
name and recursively build a
tree with all it’s submodules and subpackages. In the process, each node
analyze and fetch the public API of that module.
name can be any node, like the root package, or any subpackage or submodule
and a tree will be built from there.
name must follow the standard
“dot notation” for importing a module.
This class will not assume any special naming, or perform any complex analysis to determine what must be in the public interface. This is because it is not only a difficult problem, but it involves analyzing deeply the namespace of the module which can be quite expensive.
In general it is very difficult to determine in a module namespace what
elements are private or public declared locally, private or public but declared
in another module and brought into the module local namespace
from x import y), third party library, Python standard library, etc. At
the end, any algorithm that tries to determine this will eventually fail to
meet the requirements or expectations of the developer, leaving false positives
or removing elements expected to be present in the public API.
For example, a common scenario is that some modules, specially package entry
__init__.py, can be setup to expose the public API of their sibling
modules, possible causing several objects to be identified as part of the
public API of both modules.
Because of this the approach taken by this module follows the rule in PEP20
“Explicit is better than implicit”. In consequence, the node will consider
elements as public if they are explicitly listed in the
__all__ variables. It is up to the developer to list the elements that must
be published in the public API.
__api__ is a special variable introduced by this module, and it exists for
situation were for whatever reason the developer don’t want to list in the
__all__ variable an element that needs to be published in the public API.
This class will extract all elements identified in ONE of those listings (not
the union), with
__api__ having the precedence. If none of those variables
exists in the module then it will be assumed that no public API exists for that
module and no futher actions will be taken.
If any of those variables exists this class will iterate all elements listed in them and will catalog them in four categories:
Being Variables the default if it cannot be determined that an element belongs to any of other categories.
APINode: Tree node class for module instrospection.
Tree node class for module instrospection.
- name – Name of the current module.
- subname – Last part of the name of this module. For example if name is
my.module.anotherthe subname will be
- directory – Directory of the tree. This is a
OrderedDictthat will register all modules name with it’s associated node
APINode. All nodes of a tree share this index and thus the whole tree can be queried from any node.
- module – The loaded module.
- subnodes – A list of
APINodewith all child submodules and subpackages.
- subnodes_failed – A list of submodules and subpackages names that failed to import.
Public API categories:
- functions – A
OrderedDictof all functions found in the public API of the module.
- classes – A
OrderedDictof all classes found in the public API of the module.
- exceptions – A
OrderedDictof all exceptions found in the public API of the module.
- variables – A
OrderedDictof all other elements found in the public API of the module.
In all categories the order on which the elements are listed is preserved.
Get the depth of the current node in the tree.
Return type: int Returns: The depth of the node. For example, for node
my.add.foothe depth is 3.
Get a module node by it’s name.
This is just a helper that does lookup on the directory index.
Returns: The module node identified by
namein the tree.
Noneif the name doesn’t exists.
Check if this node has a public API.
Return type: bool Returns: True if any category has at least one element.
Check if the current node is a leaf in the tree.
A leaf node not necessarily is a module, it can be a package without modules (just the entry point
Return type: bool Returns: True if no other subnodes exists for this node.
Check if this branch of the tree is relevant.
A branch is relevant if the current node has a public API or if any of its subnodes is relevant (in order to reach relevant nodes).
Relevancy is determined at initialization by the root node.
Return type: bool Returns: True if the current node is relevant.
Check if the current node is the root node.
Return type: bool Returns: True if the current node is the root node.
Pretty print the subtree at the current node.
For example, for the module
confspec confspec.manager [c] confspec.options [c] confspec.providers [c, v] confspec.providers.dict [c] confspec.providers.ini [c] confspec.providers.json [c] confspec.utils [f] confspec.validation [f]
The tags at the right of the name shows what kind of elements are present in the public interfaces of those modules.
Traverse the tree top-down.
Returns: This method will yield tuples
(node, [leaves])for each node in the tree.