def test_name_properties_on_module(): assert not Module(name="a", path="a", file_path="a.py").name_properties assert "private" in Module(name="_a", path="a", file_path="_a.py").name_properties assert not Module(name="__a", path="__a", file_path="__a.py").name_properties assert "special" in Module(name="__a__", path="a", file_path="__a__.py").name_properties
def test_do_not_add_child_if_parent_is_not_self(): """Don't add a child the parent is not the right one.""" parent = Module(name="my_module", path="my.dotted.path", file_path="/my/absolute/path.py") child = Attribute(name="my_attribute", path="my.other.path.my_attribute", file_path="/my/absolute/path.py") parent.add_child(child) assert not parent.children assert not parent.attributes
def test_add_child(): """Add a child.""" parent = Module(name="my_module", path="my.dotted.path", file_path="/my/absolute/path.py") child = Attribute(name="my_attribute", path="my.dotted.path.my_attribute", file_path="/my/absolute/path.py") parent.add_child(child) assert parent.children[0] is child assert parent.attributes[0] is child
def test_get_root(): root = Module(name="my_module", path="my.dotted.path", file_path="") node1 = Class(name="my_class1", path="my.dotted.path.my_class1", file_path="") node2 = Class(name="my_class2", path="my.dotted.path.my_class2", file_path="") leaf = Method(name="my_method", path="my.dotted.path.my_class1.my_method", file_path="") root.add_children([node1, node2]) node1.add_child(leaf) assert root.root is root assert node1.root is root assert node2.root is root assert leaf.root is root
def get_module_documentation(self, node: ObjectNode, select_members=None) -> Module: """ Get the documentation for a module and its children. Arguments: node: The node representing the module and its parents. select_members: Explicit members to select. Returns: The documented module object. """ module = node.obj path = node.dotted_path name = path.split(".")[-1] source: Optional[Source] try: source = Source(inspect.getsource(module), 1) except OSError as error: try: code = Path(node.file_path).read_text() except (OSError, UnicodeDecodeError): self.errors.append( f"Couldn't read source for '{path}': {error}") source = None else: source = Source(code, 1) if code else None root_object = Module( name=name, path=path, file_path=node.file_path, docstring=inspect.getdoc(module), source=source, ) if select_members is False: return root_object select_members = select_members or set() attributes_data = get_module_attributes(module) root_object.parse_docstring(self.docstring_parser, attributes=attributes_data) for member_name, member in inspect.getmembers(module): if self.select(member_name, select_members): # type: ignore child_node = ObjectNode(member, member_name, parent=node) if child_node.is_class( ) and node.root.obj is inspect.getmodule(member): root_object.add_child( self.get_class_documentation(child_node)) elif child_node.is_function( ) and node.root.obj is inspect.getmodule(member): root_object.add_child( self.get_function_documentation(child_node)) elif member_name in attributes_data: root_object.add_child( self.get_attribute_documentation( child_node, attributes_data[member_name])) if hasattr(module, "__path__"): # noqa: WPS421 (hasattr) for _, modname, _ in pkgutil.iter_modules(module.__path__): if self.select(modname, select_members): leaf = get_object_tree(f"{path}.{modname}") root_object.add_child(self.get_module_documentation(leaf)) return root_object
def get_module_documentation(self, node: ObjectNode, members=None) -> Module: """ Get the documentation for a module and its children. Arguments: node: The node representing the module and its parents. members: Explicit members to select. Return: The documented module object. """ module = node.obj path = node.dotted_path name = path.split(".")[-1] source: Optional[Source] try: source = Source(inspect.getsource(module), 1) except OSError as error: try: with Path(node.file_path).open() as fd: code = fd.readlines() if code: source = Source(code, 1) else: source = None except OSError: self.errors.append( f"Couldn't read source for '{path}': {error}") source = None root_object = Module(name=name, path=path, file_path=node.file_path, docstring=inspect.getdoc(module) or "", source=source) if members is False: return root_object # type_hints = get_type_hints(module) members = members or set() for member_name, member in inspect.getmembers( module, lambda m: node.root.obj is inspect.getmodule(m)): if self.select(member_name, members): # type: ignore child_node = ObjectNode(member, member_name, parent=node) if child_node.is_class(): root_object.add_child( self.get_class_documentation(child_node)) elif child_node.is_function(): root_object.add_child( self.get_function_documentation(child_node)) try: package_path = module.__path__ except AttributeError: pass else: for _, modname, _ in pkgutil.iter_modules(package_path): if self.select(modname, members): leaf = get_object_tree(f"{path}.{modname}") root_object.add_child(self.get_module_documentation(leaf)) return root_object
def test_creating_module(): assert Module(name="my_object", path="my.dotted.path", file_path="/my/absolute/path.py")