Source code for winspsrc.scripts.generate_docs

#!/usr/bin/env python3
"""Script to generate Windows serialized property documentation."""

import argparse
import logging
import os
import sys

import winspsrc

from winspsrc import yaml_definitions_file


[docs] class IndexRstOutputWriter: """Index.rst output writer."""
[docs] def __init__(self, path): """Initializes an index.rst output writer.""" super().__init__() self._file_object = None self._path = path
[docs] def __enter__(self): """Make this work with the 'with' statement.""" self._file_object = open(self._path, "w", encoding="utf-8") text = "\n".join( [ "########################", "Serialized Property Sets", "########################", "", ".. toctree::", " :maxdepth: 1", "", "", ] ) self._file_object.write(text) return self
[docs] def __exit__(self, exception_type, value, traceback): """Make this work with the 'with' statement.""" self._file_object.close() self._file_object = None
[docs] def WritePropertySet(self, format_identifier): """Writes a property set to the index.rst file. Args: format_identifier (str): format identifier. """ self._file_object.write(f" {format_identifier:s} <{format_identifier:s}>\n")
[docs] class MarkdownOutputWriter: """Markdown output writer."""
[docs] def __init__(self, path): """Initializes a Markdown output writer.""" super().__init__() self._file_object = None self._path = path
[docs] def __enter__(self): """Make this work with the 'with' statement.""" self._file_object = open(self._path, "w", encoding="utf-8") return self
[docs] def __exit__(self, exception_type, value, traceback): """Make this work with the 'with' statement.""" self._file_object.close() self._file_object = None
[docs] def WritePropertySet(self, property_set): """Writes a property set to a Markdown file. Args: property_set (list[SerializedPropertyDefinition]): property set. """ format_identifier = property_set[0].format_identifier format_class = None for property_definition in property_set: if property_definition.format_class: format_class = property_definition.format_class break if format_class: page_header = f"## {format_identifier:s} ({format_class:s})" else: page_header = f"## {format_identifier:s}" table_header_values = [ "Property identifier", "Shell property key", "Shell name", "Alias", ] lines = [ page_header, "", " | ".join(table_header_values), " | ".join(["---"] * len(table_header_values)), ] for property_definition in sorted( property_set, key=lambda definition: definition.property_identifier ): property_identifier = property_definition.property_identifier if isinstance(property_identifier, int): property_identifier = f"{property_identifier:d}" table_row = " | ".join( [ property_identifier, ", ".join(sorted(property_definition.shell_property_keys)), ", ".join(sorted(property_definition.names)), ", ".join(sorted(property_definition.aliases)), ] ) lines.append(table_row) lines.extend(["", ""]) text = "\n".join(lines) self._file_object.write(text)
[docs] def Main(): """Entry point of console script to generate property documentation. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser( description=("Generated Windows serialized property documentation.") ) argument_parser.parse_args() logging.basicConfig(level=logging.INFO, format="[%(levelname)s] %(message)s") data_path = os.path.join(os.path.dirname(winspsrc.__file__), "data") definitions_file = yaml_definitions_file.YAMLPropertiesDefinitionsFile() property_definitions = {} path = os.path.join(data_path, "defined_properties.yaml") for property_definition in definitions_file.ReadFromFile(path): lookup_key = property_definition.lookup_key if lookup_key in property_definitions: property_definitions[lookup_key].Merge(property_definition) else: property_definitions[lookup_key] = property_definition path = os.path.join(data_path, "observed_properties.yaml") for property_definition in definitions_file.ReadFromFile(path): lookup_key = property_definition.lookup_key if lookup_key in property_definitions: property_definitions[lookup_key].Merge(property_definition) else: property_definitions[lookup_key] = property_definition path = os.path.join(data_path, "third_party_properties.yaml") for property_definition in definitions_file.ReadFromFile(path): lookup_key = property_definition.lookup_key if lookup_key in property_definitions: property_definitions[lookup_key].Merge(property_definition) else: property_definitions[lookup_key] = property_definition output_directory = os.path.join("docs", "sources", "property-sets") os.makedirs(output_directory, exist_ok=True) index_rst_file_path = os.path.join(output_directory, "index.rst") with IndexRstOutputWriter(index_rst_file_path) as index_rst_writer: last_format_identifier = None property_set = [] for _, property_definition in sorted(property_definitions.items()): if last_format_identifier != property_definition.format_identifier: if property_set: markdown_file_path = os.path.join( output_directory, f"{last_format_identifier:s}.md" ) with MarkdownOutputWriter(markdown_file_path) as markdown_writer: markdown_writer.WritePropertySet(property_set) property_set = [] index_rst_writer.WritePropertySet(last_format_identifier) last_format_identifier = property_definition.format_identifier property_set.append(property_definition) if property_set: if property_set: markdown_file_path = os.path.join( output_directory, f"{last_format_identifier:s}.md" ) with MarkdownOutputWriter(markdown_file_path) as markdown_writer: markdown_writer.WritePropertySet(property_set) property_set = [] index_rst_writer.WritePropertySet(last_format_identifier) return 0
if __name__ == "__main__": sys.exit(Main())