Source code for coalib.bearlib.languages.documentation.DocstyleDefinition

from collections import Iterable, namedtuple
from glob import iglob
import os.path

from coala_utils.decorators import (
    enforce_signature, generate_eq, generate_repr)
from coalib.parsing.ConfParser import ConfParser


[docs]@generate_repr() @generate_eq('language', 'docstyle', 'markers') class DocstyleDefinition: """ The DocstyleDefinition class holds values that identify a certain type of documentation comment (for which language, documentation style/tool used etc.). """ Metadata = namedtuple('Metadata', ('param_start', 'param_end', 'exception_start', 'exception_end', 'return_sep')) ClassPadding = namedtuple('ClassPadding', ('top_padding', 'bottom_padding')) FunctionPadding = namedtuple('FunctionPadding', ('top_padding', 'bottom_padding')) DocstringTypeRegex = namedtuple('DocstringTypeRegex', ('class_sign', 'func_sign')) @enforce_signature def __init__(self, language: str, docstyle: str, markers: (Iterable, str), metadata: Metadata, class_padding: ClassPadding, function_padding: FunctionPadding, docstring_type_regex: DocstringTypeRegex, docstring_position: str): """ Instantiates a new DocstyleDefinition. :param language: The case insensitive programming language of the documentation comment, e.g. ``"CPP"`` for C++ or ``"PYTHON3"``. :param docstyle: The case insensitive documentation style/tool used to document code, e.g. ``"default"`` or ``"doxygen"``. :param markers: An iterable of marker/delimiter string iterables or a single marker/delimiter string iterable that identify a documentation comment. See ``markers`` property for more details on markers. :param metadata: A namedtuple consisting of certain attributes that form the layout of the certain documentation comment e.g. ``param_start`` defining the start symbol of the parameter fields and ``param_end`` defining the end. :param class_padding: A namedtuple consisting of values about blank lines before and after the documentation of ``docstring_type`` class. :param function_padding: A namedtuple consisting of values about blank lines before and after the documentation of ``docstring_type`` function. :param docstring_type_regex: A namedtuple consisting of regex about ``class`` and ``function`` of a language, which is used to determine ``docstring_type`` of DocumentationComment. :param docstring_position: Defines the position where the regex of docstring type is present(i.e. ``top`` or ``bottom``). """ self._language = language.lower() self._docstyle = docstyle.lower() # Check and modify tuple if only one marker_set exists. markers = tuple(markers) if len(markers) == 3 and all(isinstance(x, str) for x in markers): markers = (markers,) self._markers = tuple(tuple(marker_set) for marker_set in markers) # Check marker set dimensions. for marker_set in self._markers: length = len(marker_set) if length != 3: raise ValueError('Length of a given marker set was not 3 (was ' 'actually {}).'.format(length)) self._metadata = metadata self._class_padding = class_padding self._function_padding = function_padding self._docstring_type_regex = docstring_type_regex self._docstring_position = docstring_position @property def language(self): """ The programming language. :return: A lower-case string defining the programming language (i.e. "cpp" or "python"). """ return self._language @property def docstyle(self): """ The documentation style/tool used to document code. :return: A lower-case string defining the docstyle (i.e. "default" or "doxygen"). """ return self._docstyle @property def markers(self): """ A tuple of marker sets that identify a documentation comment. Marker sets consist of 3 entries where the first is the start-marker, the second one the each-line marker and the last one the end-marker. For example a marker tuple with a single marker set ``(("/**", "*", "*/"),)`` would match following documentation comment: :: /** * This is documentation. */ It's also possible to supply an empty each-line marker (``("/**", "", "*/")``): :: /** This is more documentation. */ Markers are matched "greedy", that means it will match as many each-line markers as possible. I.e. for ``("///", "///", "///")``): :: /// Brief documentation. /// /// Detailed documentation. :return: A tuple of marker/delimiter string tuples that identify a documentation comment. """ return self._markers @property def metadata(self): """ A namedtuple of certain attributes present in the documentation. These attributes are used to define parts of the documentation. """ return self._metadata @property def class_padding(self): """ A namedtuple ``ClassPadding`` consisting of values about blank lines before and after the documentation of ``docstring_type`` class. These values are official standard of following blank lines before and after the documentation of ``docstring_type`` class. """ return self._class_padding @property def function_padding(self): """ A namedtuple ``FunctionPadding`` consisting of values about blank lines before and after the documentation of ``docstring_type`` function. These values are official standard of following blank lines before and after the documentation of ``docstring_type`` function. """ return self._function_padding @property def docstring_type_regex(self): """ A namedtuple ``DocstringTypeRegex`` consisting of regex about ``class`` and ``function`` of a language, which is used to determine ``docstring_type`` of DocumentationComment. """ return self._docstring_type_regex @property def docstring_position(self): """ Defines the position, where the regex of docstring type is present. Depending on different languages the docstrings are present below or above the defined class or function. This expicitly defines where the class regex or function regex is present(i.e. ``top`` or ``bottom``). """ return self._docstring_position
[docs] @classmethod @enforce_signature def load(cls, language: str, docstyle: str, coalang_dir=None): """ Loads a ``DocstyleDefinition`` from the coala docstyle definition files. This function considers all settings inside the according coalang-files as markers, except ``param_start``, ``param_end`` and ``return_sep`` which are considered as special metadata markers. .. note:: When placing new coala docstyle definition files, these must consist of only lowercase letters and end with ``.coalang``! :param language: The case insensitive programming language of the documentation comment as a string. :param docstyle: The case insensitive documentation style/tool used to document code, e.g. ``"default"`` or ``"doxygen"``. :param coalang_dir: Path to directory with coalang docstyle definition files. This replaces the default path if given. :raises FileNotFoundError: Raised when the given docstyle was not found. :raises KeyError: Raised when the given language is not defined for given docstyle. :return: The ``DocstyleDefinition`` for given language and docstyle. """ docstyle = docstyle.lower() language_config_parser = ConfParser(remove_empty_iter_elements=False) coalang_file = os.path.join( coalang_dir or os.path.dirname(__file__), docstyle + '.coalang') try: docstyle_settings = language_config_parser.parse(coalang_file) except FileNotFoundError: raise FileNotFoundError('Docstyle definition ' + repr(docstyle) + ' not found.') language = language.lower() try: docstyle_settings = docstyle_settings[language] except KeyError: raise KeyError('Language {!r} is not defined for docstyle {!r}.' .format(language, docstyle)) metadata_settings = ('param_start', 'param_end', 'exception_start', 'exception_end', 'return_sep') metadata = cls.Metadata(*(str(docstyle_settings.get(req_setting, '')) for req_setting in metadata_settings)) try: class_padding = cls.ClassPadding( *(int(padding) for padding in tuple( docstyle_settings['class_padding']))) except IndexError: class_padding = cls.ClassPadding('', '') try: function_padding = cls.FunctionPadding( *(int(padding) for padding in tuple( docstyle_settings['function_padding']))) except IndexError: function_padding = cls.FunctionPadding('', '') try: docstring_type_regex = cls.DocstringTypeRegex( *(str(sign) for sign in tuple( docstyle_settings['docstring_type_regex']))) except IndexError: docstring_type_regex = cls.DocstringTypeRegex('', '') try: docstring_position = docstyle_settings['docstring_position'].value except IndexError: docstring_position = '' ignore_keys = (('class_padding', 'function_padding', 'docstring_type_regex', 'docstring_position') + metadata_settings) marker_sets = (tuple(value) for key, value in docstyle_settings.contents.items() if key not in ignore_keys and not key.startswith('comment')) return cls(language, docstyle, marker_sets, metadata, class_padding, function_padding, docstring_type_regex, docstring_position)
[docs] @staticmethod def get_available_definitions(): """ Returns a sequence of pairs with ``(docstyle, language)`` which are available when using ``load()``. :return: A sequence of pairs with ``(docstyle, language)``. """ pattern = os.path.join(os.path.dirname(__file__), '*.coalang') for coalang_file in iglob(pattern): docstyle = os.path.splitext(os.path.basename(coalang_file))[0] # Ignore files that are not lowercase, as coalang files have to be. if docstyle.lower() == docstyle: parser = ConfParser(remove_empty_iter_elements=False) for language in parser.parse(coalang_file): yield docstyle, language.lower()