Source code for pyVHDLModelUtils.sphinx

from typing import List, Union
from pathlib import Path
from textwrap import indent
from io import StringIO
from contextlib import redirect_stdout
from tabulate import tabulate

from pyGHDL.dom.NonStandard import Design, Document, Library
from pyGHDL.dom.DesignUnit import Entity

from pyVHDLModelUtils.resolve import Symbols as resolve_Symbols
from pyVHDLModelUtils.fmt import SubtypeIndication as format_SubtypeIndication


DESIGN = Design()


[docs] def initDesign(root: Union[str, Path], **kwargs) -> None: """ Initialize a Design and analyze sources. Each argument after `root` defines a library name and the type is expected to be a list of patterns. :param root: Location of the root for all provided relative paths. This is relative to the base directory of the build. """ root = Path(root) if isinstance(root, str) else root print(".. NOTE:: Output of initDesign:\n") for library, patterns in kwargs.items(): lib = DESIGN.GetLibrary(library) print(" * {0}\n".format(library)) for pattern in patterns: for item in root.glob(pattern): # FIXME: is_relative_to is new in Python 3.9 (see https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.is_relative_to) # Therefore, we use try..except for backwards compatibility. # print(" * {0}\n".format(item.relative_to(root) if item.is_relative_to(root) else item)) try: path = item.relative_to(root) except e: path = item print(" * {0}\n".format(path)) f = StringIO() with redirect_stdout(f): DESIGN.AddDocument(Document(item), lib) print(indent(f.getvalue(), " * ")) print("") resolve_Symbols(DESIGN)
STYLES = ["rst:list", "rst:table"]
[docs] def printDocumentationOfEntity_rstList(entity: Entity, lib: Library = None) -> None: """ Print documentation of an Entity using style 'rst:list'. """ print("Entity *{0}* from Library *{1}*:\n".format(entity.Identifier, lib.Identifier)) print("* Generics:\n") for generic in entity.GenericItems: print( " * *{0}* : ``{1}``{2}".format( ", ".join(generic.Identifiers), format_SubtypeIndication(generic.Subtype), "" if generic.DefaultExpression is None else " := ``{0!s}``".format(generic.DefaultExpression), ) ) print("\n* Ports:\n") for port in entity.PortItems: print( " * *{0}* : {1} ``{2}``{3}".format( ", ".join(port.Identifiers), port.Mode, format_SubtypeIndication(port.Subtype), "" if port.DefaultExpression is None else " := ``{0!s}``".format(port.DefaultExpression), ) ) print("\n* Architectures:\n") for architecture in entity.Architectures: print(" * *{0}*".format(architecture.Identifier))
[docs] def printDocumentationOfEntity_rstTable(entity: Entity, lib: Library = None) -> None: """ Print documentation of an Entity using style 'rst:table' (through 'tabulate'). """ def printTable(data, headers=None, caption=None): table = tabulate(data, tablefmt="rst") if headers is None else tabulate(data, headers, tablefmt="rst") if caption is not None: print(".. table:: {0}\n :align: center\n".format(caption)) print(indent(table, " ")) else: print(table) print("\n") name = "{0}{1}".format("" if lib is None else "{0}.".format(lib.Identifier), entity.Identifier) printTable( [ [ ", ".join(generic.Identifiers), "``{0}``".format(format_SubtypeIndication(generic.Subtype)), "" if generic.DefaultExpression is None else "``{0!s}``".format(generic.DefaultExpression), ] for generic in entity.GenericItems ], headers=["Identifiers", "Type", "Default"], caption="{0} Generics".format(name), ) printTable( [ [ ", ".join(port.Identifiers), port.Mode, "``{0}``".format(format_SubtypeIndication(port.Subtype)), "" if port.DefaultExpression is None else "``{0!s}``".format(port.DefaultExpression), ] for port in entity.PortItems ], headers=["Identifiers", "Mode", "Type", "Default"], caption="{0} Ports".format(name), ) printTable( [ [ architecture.Identifier, len(architecture.Statements), ] for architecture in entity.Architectures ], headers=["Identifier", "Number of statements"], caption="{0} Architectures".format(name), )
[docs] def printDocumentationOf(targets: List[str] = None, style: str = "rst:list") -> None: """ Generate documentation of resources (either a unit or a whole file). Supported syntaxes: * libraryName.entityName * TODO: libraryName.entityName(architectureName) * TODO: libraryName.packageName * TODO: libraryName.configurationName * TODO: libraryName.architectureName * TODO: relative/path/to/file * TODO: absolute/path/to/file :param targets: list of resources to generate the documentation for. :param style: format of the output. Supported values are: 'rst:list' and 'rst:table'. """ if targets is None: print("Design content:\n") for libName, lib in DESIGN.Libraries.items(): ents = lib.Entities print("* Library *{0}* [{1} entities]\n".format(libName, len(ents))) for ent in ents: print(" * Entity: *{0}*\n".format(ent.Identifier)) for arch in ent.Architectures: print(" * Architecture: *{0}*\n".format(arch.Identifier)) print("") return if style not in STYLES: raise Exception("Unknown style <{0}>".format(style)) for target in targets: # TODO: support other argument types: # - libName.packageName # - path/to/file (print all the units in the file) parts = target.split(".") assert len(parts) == 2 libName, entityName = parts lib = DESIGN.GetLibrary(libName) entity = None for entity in lib.Entities: if entity.Identifier == entityName: break else: raise Exception("Entity {0} not found in library {1}.".format(entityName, libraryName)) if style == "rst:list": printDocumentationOfEntity_rstList(entity, lib) continue if style == "rst:table": printDocumentationOfEntity_rstTable(entity, lib) continue