diff --git a/src/jcloud_docsgen/cli/cli.py b/src/jcloud_docsgen/cli/cli.py index 4205064..1ebdce9 100644 --- a/src/jcloud_docsgen/cli/cli.py +++ b/src/jcloud_docsgen/cli/cli.py @@ -12,9 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -''' +""" The command line interface -''' +""" import argparse import pathlib @@ -31,80 +31,81 @@ __all__ = [ _LANG_PYTHON = 'python' _PROGRAM_NAME = 'jcloud-docsgen' + def existing_directory(path: str) -> pathlib.Path: _path = path path = pathlib.Path(_path) if not path.exists(): - raise argparse.ArgumentTypeError( - f'{_path}: no such file or directory' - ) + raise argparse.ArgumentTypeError(f'{_path}: no such file or directory') if not path.is_dir(): raise argparse.ArgumentTypeError(f'{_path}: not a directory') return path + def error(message: str, exit_code: int = 1): - ''' + """ Shows an error message and returns the exit code. :param message: The error message to show. :type message: str :param exit_code: The exit code. :type exit_code: int - ''' + """ - print(f'{_PROGRAM_NAME}: error: {message}', file = sys.stderr) + print(f'{_PROGRAM_NAME}: error: {message}', file=sys.stderr) return exit_code + def create_argument_parser() -> argparse.ArgumentParser: - ''' + """ Prepares a parser to parse the command-line arguments using argparse. :return: The parser. :rtype: argparse.ArgumentParser - ''' + """ - common_parser = argparse.ArgumentParser(add_help = False) + common_parser = argparse.ArgumentParser(add_help=False) common_parser.add_argument( 'project_directory', - type = existing_directory, - nargs = '?', - default = pathlib.Path('.'), - help = 'The directory of the project', + type=existing_directory, + nargs='?', + default=pathlib.Path('.'), + help='The directory of the project', ) common_parser.add_argument( '-o', '--output-dir', - type = pathlib.Path, - help = 'the output directory the documentation will be written to', + type=pathlib.Path, + help='the output directory the documentation will be written to', ) argument_parser = argparse.ArgumentParser() subparsers = argument_parser.add_subparsers( - dest = 'language', - required = True, + dest='language', + required=True, ) python_parser = subparsers.add_parser( _LANG_PYTHON, - parents = [common_parser], - help = 'generate documentation for Python project', + parents=[common_parser], + help='generate documentation for Python project', ) python_parser.add_argument( '-s', '--sections', - nargs = '+', - choices = VALID_PYTHON_SECTIONS, - help = 'the sections to be included in the documentation', + nargs='+', + choices=VALID_PYTHON_SECTIONS, + help='the sections to be included in the documentation', ) python_parser.add_argument( '-S', '--sections-exclude', - nargs = '+', - default = [], - choices = VALID_PYTHON_SECTIONS, - help = ( + nargs='+', + default=[], + choices=VALID_PYTHON_SECTIONS, + help=( 'the sections to be excluded in the documentation. ' 'If a section shall be included AND excluded, it is excluded.' ), @@ -112,8 +113,8 @@ def create_argument_parser() -> argparse.ArgumentParser: python_parser.add_argument( '-H', '--allow-html', - action = 'store_true', - help = ( + action='store_true', + help=( 'indicates whether HTML is allowed in the documentation. ' 'By default, HTML is disabled.' ), @@ -121,8 +122,8 @@ def create_argument_parser() -> argparse.ArgumentParser: python_parser.add_argument( '-T', '--allow-tables', - action = 'store_true', - help = ( + action='store_true', + help=( 'indicates whether Markdown tables are allowed in the ' 'documentation. By default, Markdown tables are disabled. ' 'Warning: Markdown tables are not CommonMark.' @@ -131,7 +132,8 @@ def create_argument_parser() -> argparse.ArgumentParser: return argument_parser -def main(argv = None) -> int: + +def main(argv=None) -> int: argument_parser = create_argument_parser() args = argument_parser.parse_args(argv) @@ -141,13 +143,14 @@ def main(argv = None) -> int: try: if args.language == _LANG_PYTHON: from .languages.python import generate + generate( args.project_directory, args.output_dir, - include_sections = args.sections, - exclude_sections = args.sections_exclude, - allow_html = args.allow_html, - allow_tables = args.allow_tables, + include_sections=args.sections, + exclude_sections=args.sections_exclude, + allow_html=args.allow_html, + allow_tables=args.allow_tables, ) except FileNotFoundError as exc: return error(f'{exc.filename}: no such file or directory') diff --git a/src/jcloud_docsgen/cli/languages/python.py b/src/jcloud_docsgen/cli/languages/python.py index ab4bbce..df0dff6 100644 --- a/src/jcloud_docsgen/cli/languages/python.py +++ b/src/jcloud_docsgen/cli/languages/python.py @@ -29,11 +29,12 @@ VALID_SECTIONS = list( PythonDefinitionDocumentationIncludeSections()._args.keys() ) + def parse_sections_list( include_sections: Optional[list[str]] = None, exclude_sections: list[str] = [], ) -> PythonDefinitionDocumentationIncludeSections: - ''' + """ Returns a Python definition documentation sections list from the sections list to be included and the sections list to be excluded. These lists both consist of the sections as strings which contain @@ -46,7 +47,7 @@ def parse_sections_list( :return: The Python definition documentation sections object. :rtype: PythonDefinitionDocumentationIncludeSections - ''' + """ if include_sections is None: include_sections = VALID_SECTIONS[:] @@ -56,17 +57,18 @@ def parse_sections_list( del include_sections[include_sections.index(section)] return PythonDefinitionDocumentationIncludeSections( - signature = 'signature' in include_sections, - returns = 'returns' in include_sections, - params = 'params' in include_sections, - exceptions = 'exceptions' in include_sections, - examples = 'examples' in include_sections, - docstring = 'docstring' in include_sections, - bases = 'bases' in include_sections, - decorators = 'decorators' in include_sections, - class_body = 'class_body' in include_sections, + signature='signature' in include_sections, + returns='returns' in include_sections, + params='params' in include_sections, + exceptions='exceptions' in include_sections, + examples='examples' in include_sections, + docstring='docstring' in include_sections, + bases='bases' in include_sections, + decorators='decorators' in include_sections, + class_body='class_body' in include_sections, ) + def _generate( project_directory: pathlib.Path, output_directory: pathlib.Path, @@ -77,7 +79,7 @@ def _generate( allow_html: bool = False, allow_tables: bool = False, ) -> None: - ''' + """ Generates the documentation for a Python project. :param project_directory: The project directory. @@ -92,17 +94,18 @@ def _generate( :type allow_html: bool :param allow_tables: Indicates whether Markdown tables are allowed. Warning: Markdown tables are not CommonMark. - ''' + """ docs_generator = PythonDocumentationGenerator( project_directory, output_directory, - include_sections = include_sections, - allow_html = allow_html, - allow_tables = allow_tables, + include_sections=include_sections, + allow_html=allow_html, + allow_tables=allow_tables, ) docs_generator.generate_documentation() + def generate( project_directory: pathlib.Path, output_directory: pathlib.Path, @@ -112,7 +115,7 @@ def generate( allow_html: bool = False, allow_tables: bool = False, ) -> None: - ''' + """ Generates the documentation for a Python project. :param project_directory: The project directory. @@ -130,14 +133,14 @@ def generate( :type allow_html: bool :param allow_tables: Indicates whether Markdown tables are allowed. Warning: Markdown tables are not CommonMark. - ''' + """ sections = parse_sections_list(include_sections, exclude_sections) _generate( project_directory, output_directory, - include_sections = sections, - allow_html = allow_html, - allow_tables = allow_tables, + include_sections=sections, + allow_html=allow_html, + allow_tables=allow_tables, ) diff --git a/src/jcloud_docsgen/core/python/_core.py b/src/jcloud_docsgen/core/python/_core.py index cf4ba2c..5fe9d1b 100644 --- a/src/jcloud_docsgen/core/python/_core.py +++ b/src/jcloud_docsgen/core/python/_core.py @@ -40,15 +40,16 @@ __all__ = [ 'PythonDocumentationGenerator', ] + def _collect_definitions(tree_or_node) -> Iterator[PythonDefinition]: - ''' + """ Collects all definitions of the tree or node. :param tree_or_node: The tree or node. :return: The definitions. :rtype: Iterator[PythonDefinition] - ''' + """ for node in tree_or_node.body: if isinstance(node, ast.FunctionDef): @@ -58,6 +59,7 @@ def _collect_definitions(tree_or_node) -> Iterator[PythonDefinition]: if isinstance(node, ast.ClassDef): yield PythonClassDefinition.from_node(node) + _Arguments: TypeAlias = tuple[ list[PythonFunctionArgument], list[PythonFunctionArgument], @@ -66,10 +68,11 @@ _Arguments: TypeAlias = tuple[ Union[PythonFunctionArgument, None], ] + def _group_argument_list( argument_list: list[PythonFunctionArgument], ) -> _Arguments: - ''' + """ Groups the argument list into a list of positional-only arguments, a list of normal arguments, the * argument if there is one, a list of keyword-only arguments and the var-keyword-argument if there is one. @@ -78,13 +81,12 @@ def _group_argument_list( :type argument_list: list[PythonFunctionArgument] :rtype: _Arguments - ''' + """ if argument_list: - if argument_list[-1].kind != PythonArgumentKind.KWARGS and any([ - arg.kind == PythonArgumentKind.KWARGS - for arg in argument_list - ]): + if argument_list[-1].kind != PythonArgumentKind.KWARGS and any( + [arg.kind == PythonArgumentKind.KWARGS for arg in argument_list] + ): raise PythonArgumentStructureError( 'arguments cannot follow var-keyword argument', ) @@ -106,7 +108,7 @@ def _group_argument_list( if vararg is not None: raise PythonArgumentStructureError( '* argument may only appear once', - definition = arg, + definition=arg, ) vararg = arg @@ -124,10 +126,11 @@ def _group_argument_list( kwargs, ) + def _signature_argument_list( argument_list: list[PythonFunctionArgument], ) -> list[str]: - ''' + """ Returns a list of the arguments as strings for a function signature. :param argument_list: The argument list. @@ -135,7 +138,7 @@ def _signature_argument_list( :return: The list of function signature argument strings. :rtype: list[str] - ''' + """ ( positional_only_args, @@ -170,8 +173,9 @@ def _signature_argument_list( return args + def _fit_row_length(expected: int, row: tuple) -> tuple: - ''' + """ Fits the row length to the expected length. If the row is too long, the tail, that makes it too long, is omitted. @@ -181,7 +185,7 @@ def _fit_row_length(expected: int, row: tuple) -> tuple: :type expected: int :param row: The row. :type row: tuple - ''' + """ if expected < 0: raise ValueError('expected must be larger than or equal 0.') @@ -191,6 +195,7 @@ def _fit_row_length(expected: int, row: tuple) -> tuple: else: return row + (None,) * (expected - len(row)) + def _markdown_table( header: tuple, body: list[tuple], @@ -200,7 +205,7 @@ def _markdown_table( one_line_values: bool = True, missing_value: str = '--', ) -> str: - ''' + """ Generates a table. If ``allow_markdown_table`` is ``False``, an alternative @@ -222,7 +227,7 @@ def _markdown_table( :param missing_value: The string that is used if a value is missing (only if ``force_row_lengths`` is ``False``). :type missing_value: str - ''' + """ if not header or not body: return '' @@ -231,37 +236,34 @@ def _markdown_table( if allow_markdown_table: table = ( - '| ' \ - + ' | '.join(header) \ - + ' |\n|' \ - + ' --- |' * len(header) \ - + '\n' + '| ' + ' | '.join(header) + ' |\n|' + ' --- |' * len(header) + '\n' ) - for row in body: if len(row) != header_len: if force_row_lengths: raise ValueError( f'expected {header_len} value{ - "s" - if header_len > 1 - else "" + "s" if header_len > 1 else "" }, got {len(row)}', ) else: row = _fit_row_length(header_len, row) - table += '| ' + ' | '.join([ - str( - col - if col is not None - else missing_value - ).replace('\n', ' ') - if one_line_values - else str(col if col is not None else missing_value) - for col in row - ]) + ' |\n' + table += ( + '| ' + + ' | '.join( + [ + str(col if col is not None else missing_value).replace( + '\n', ' ' + ) + if one_line_values + else str(col if col is not None else missing_value) + for col in row + ] + ) + + ' |\n' + ) else: table = '' @@ -270,9 +272,7 @@ def _markdown_table( if force_row_lengths: raise ValueError( f'expected {header_len} value{ - "s" - if header_len > 1 - else "" + "s" if header_len > 1 else "" }, got {len(row)}', ) else: @@ -281,29 +281,25 @@ def _markdown_table( sep = '- ' for i, col in enumerate(row): table += ( - sep \ - + header[i] \ - + ': ' \ + sep + + header[i] + + ': ' + ( - str( - col - if col is not None - else missing_value - ).replace('\n', ' ') \ - if one_line_values \ - else str( - col - if col is not None - else missing_value + str(col if col is not None else missing_value).replace( + '\n', ' ' ) - ) + '\n\n' + if one_line_values + else str(col if col is not None else missing_value) + ) + + '\n\n' ) sep = ' ' return table.strip() + def _is_docstring(docstring: Union[str, PythonDocstring, None]) -> bool: - ''' + """ Checks whether the docstring is a docstring or an empty docstring. :param docstring: The docstring. @@ -311,7 +307,7 @@ def _is_docstring(docstring: Union[str, PythonDocstring, None]) -> bool: :return: Whether there is a docstring. :rtype: bool - ''' + """ if docstring is None: return False @@ -321,11 +317,13 @@ def _is_docstring(docstring: Union[str, PythonDocstring, None]) -> bool: return docstring.strip() != '' + @dataclass class _FunctionParamInfo: annotation: Union[str, None] description: Union[str, None] + @dataclass class _NoDocstringTemplate: description = None @@ -340,10 +338,12 @@ class _NoDocstringTemplate: long_description = None blank_after_short_description = None + _NoDocstring = _NoDocstringTemplate() + def _argument_kind_human_readable(argument_kind: PythonArgumentKind) -> str: - ''' + """ Returns the human-readable representation of a ``PythonArgumentKind``. @@ -352,15 +352,16 @@ def _argument_kind_human_readable(argument_kind: PythonArgumentKind) -> str: :return: The human-readable representation. :rtype: str - ''' + """ return argument_kind.name.lower().replace('_', '-') + def _function_params_info( arg_list: list[PythonFunctionArgument], docstring_arg_list: list[docstring_parser.DocstringParam], ) -> dict[str, _FunctionParamInfo]: - ''' + """ Returns a dictionary with the parameter info. The keys of the dictionary are the parameter names and the values are @@ -377,11 +378,10 @@ def _function_params_info( :return: The dictionary with the parameter types. :rtype: dict[str, _FunctionParamInfo] - ''' + """ arg_annotations = { - arg.name: _FunctionParamInfo(arg.annotation, None) - for arg in arg_list + arg.name: _FunctionParamInfo(arg.annotation, None) for arg in arg_list } for arg in docstring_arg_list: @@ -393,8 +393,9 @@ def _function_params_info( return arg_annotations + class PythonDefinitionDocumentationIncludeSections: - ''' + """ A class representing the included sections in a Python definition documentation. @@ -414,50 +415,55 @@ class PythonDefinitionDocumentationIncludeSections: :type bases: bool :param decorators: Whether include the decorators section. :type decorators: bool - ''' + """ def __init__( - self, - *, - signature: bool = True, - returns: bool = True, - params: bool = True, - exceptions: bool = True, - examples: bool = True, - docstring: bool = True, - bases: bool = True, - decorators: bool = True, - class_body: bool = True, - ): - self.signature = signature - self.returns = returns - self.params = params - self.exceptions = exceptions - self.examples = examples - self.docstring = docstring - self.bases = bases - self.decorators = decorators - self.class_body = class_body + self, + *, + signature: bool = True, + returns: bool = True, + params: bool = True, + exceptions: bool = True, + examples: bool = True, + docstring: bool = True, + bases: bool = True, + decorators: bool = True, + class_body: bool = True, + ): + self.signature = signature + self.returns = returns + self.params = params + self.exceptions = exceptions + self.examples = examples + self.docstring = docstring + self.bases = bases + self.decorators = decorators + self.class_body = class_body - self._args = { - 'signature': self.signature, - 'returns': self.returns, - 'params': self.params, - 'exceptions': self.exceptions, - 'examples': self.examples, - 'docstring': self.docstring, - 'bases': self.bases, - 'decorators': self.decorators, - 'class_body': self.class_body, - } + self._args = { + 'signature': self.signature, + 'returns': self.returns, + 'params': self.params, + 'exceptions': self.exceptions, + 'examples': self.examples, + 'docstring': self.docstring, + 'bases': self.bases, + 'decorators': self.decorators, + 'class_body': self.class_body, + } def __repr__(self) -> str: - return type(self).__name__+ '(' + ', '.join( - [ - key + ' = ' + repr(value) - for key, value in self._args.items() - ], - ) + ')' + return ( + type(self).__name__ + + '(' + + ', '.join( + [ + key + ' = ' + repr(value) + for key, value in self._args.items() + ], + ) + + ')' + ) def __eq__(self, value) -> str: if not isinstance( @@ -467,8 +473,9 @@ class PythonDefinitionDocumentationIncludeSections: return False return self._args == value._args + class PythonDefinitionDocumentationGenerator: - ''' + """ A documentation generator for a Python definition. :param definition: The Python definition. @@ -492,21 +499,21 @@ class PythonDefinitionDocumentationGenerator: :type skip_empty_sections: bool :param is_method: Controls whether the definition is a class method. :type is_method: bool - ''' + """ def __init__( - self, - definition: PythonDefinition, - include_sections: PythonDefinitionDocumentationIncludeSections = ( - PythonDefinitionDocumentationIncludeSections() - ), - level: int = 1, - *, - allow_html: bool = True, - allow_tables: bool = False, - skip_empty_sections: bool = True, - is_method: bool = False, - ) -> None: + self, + definition: PythonDefinition, + include_sections: PythonDefinitionDocumentationIncludeSections = ( + PythonDefinitionDocumentationIncludeSections() + ), + level: int = 1, + *, + allow_html: bool = True, + allow_tables: bool = False, + skip_empty_sections: bool = True, + is_method: bool = False, + ) -> None: self.definition = definition self.include_sections = include_sections @@ -521,13 +528,15 @@ class PythonDefinitionDocumentationGenerator: @property def _docstring(self): if self._docstring_cache is None: - self._docstring_cache = self.definition.doc.parse() \ - if _is_docstring(self.definition.doc) \ + self._docstring_cache = ( + self.definition.doc.parse() + if _is_docstring(self.definition.doc) else _NoDocstring + ) return self._docstring_cache def generate_signature(self) -> str: - ''' + """ Generates the signature of the definition. Works only if the definition is a function or asynchronous function definition. @@ -535,18 +544,23 @@ class PythonDefinitionDocumentationGenerator: :return: The signature. :rtype: str - ''' + """ if isinstance(self.definition, PythonClassDefinition): raise TypeError( 'Cannot generate a signature of a class definition.', ) - signature = self.definition.name + '(' + ', '.join( - _signature_argument_list( - self.definition.args, - ), - ) + ')' + signature = ( + self.definition.name + + '(' + + ', '.join( + _signature_argument_list( + self.definition.args, + ), + ) + + ')' + ) if self.definition.returns is not None: signature += ' -> ' + self.definition.returns @@ -554,38 +568,38 @@ class PythonDefinitionDocumentationGenerator: return signature.strip() def _generate_signature_section(self) -> str: - ''' + """ Generates the signature section. :return: The signature section. :rtype: str - ''' + """ definition_type = 'Function' if not self.is_method else 'Method' - heading = self.level * '#' + '# ' + (definition_type) +' signature' - return f'''{heading} + heading = self.level * '#' + '# ' + (definition_type) + ' signature' + return f"""{heading} ```python {self.generate_signature()} -```''' +```""" def _generate_docstring_section(self) -> str: - ''' + """ Generates the docstring section. :return: The docstring section. :rtype: str - ''' + """ md = '' if _is_docstring(self.definition.doc) or not self.skip_empty_sections: if self.allow_html: - md += f'
Docstring' + md += f'
Docstring' else: md += self.level * '#' + '# Docstring\n\n' @@ -602,12 +616,12 @@ class PythonDefinitionDocumentationGenerator: return md.strip() def _generate_params_section(self) -> str: - ''' + """ Generates the parameters section. :return: The parameters section. :rtype: str - ''' + """ md = '' @@ -636,7 +650,7 @@ class PythonDefinitionDocumentationGenerator: ) for arg in self.definition.args ], - allow_markdown_table = self.allow_tables, + allow_markdown_table=self.allow_tables, ) md += '\n\n' @@ -647,12 +661,12 @@ class PythonDefinitionDocumentationGenerator: return md.strip() def _generate_returns_section(self) -> str: - ''' + """ Generates the returns section. :return: The returns section. :rtype: str - ''' + """ md = '' @@ -686,12 +700,12 @@ class PythonDefinitionDocumentationGenerator: return md.strip() def _generate_exceptions_section(self) -> str: - ''' + """ Generates the exceptions section. :return: The exceptions section. :rtype: str - ''' + """ md = '' @@ -699,26 +713,31 @@ class PythonDefinitionDocumentationGenerator: md += self.level * '#' + '# Exceptions\n\n' if self._docstring.raises: - md += _markdown_table(('Exception', 'Description'), [ - ( - ('`' + exception.type_name + '`') - if exception.type_name is not None - else None, non_empty_str(exception.description) - ) - for exception in self._docstring.raises - ], allow_markdown_table = self.allow_tables) + md += _markdown_table( + ('Exception', 'Description'), + [ + ( + ('`' + exception.type_name + '`') + if exception.type_name is not None + else None, + non_empty_str(exception.description), + ) + for exception in self._docstring.raises + ], + allow_markdown_table=self.allow_tables, + ) elif not self.skip_empty_sections: md += 'This function raises no exceptions.' return md.strip() def _generate_examples_section(self) -> str: - ''' + """ Generates the examples section. :return: The examples section. :rtype: str - ''' + """ md = '' @@ -727,9 +746,11 @@ class PythonDefinitionDocumentationGenerator: examples = [] for example in self._docstring.examples: - examples.append('```python\n' +\ - (example.snippet or example.description) + \ - '\n```') + examples.append( + '```python\n' + + (example.snippet or example.description) + + '\n```' + ) md += '\n\n---\n\n'.join(examples) if not self._docstring.examples and not self.skip_empty_sections: @@ -738,12 +759,12 @@ class PythonDefinitionDocumentationGenerator: return md.strip() def _generate_decorators_section(self) -> str: - ''' + """ Generates the decorators section. :return: The decorators section. :rtype: str - ''' + """ md = '' @@ -759,12 +780,12 @@ class PythonDefinitionDocumentationGenerator: return md.strip() def _generate_bases_section(self) -> str: - ''' + """ Generates the bases section. :return: The bases section. :rtype: str - ''' + """ md = '' @@ -780,12 +801,12 @@ class PythonDefinitionDocumentationGenerator: return md.strip() def _generate_body_section(self) -> str: - ''' + """ Generates the body section. :return: The body section. :rtype: str - ''' + """ md = '' @@ -793,15 +814,18 @@ class PythonDefinitionDocumentationGenerator: md += self.level * '#' + '# Body\n\n' for method_or_class in self.definition.body: - md += PythonDefinitionDocumentationGenerator( - method_or_class, - self.include_sections, - level = self.level + 2, - allow_html = self.allow_html, - allow_tables = self.allow_tables, - skip_empty_sections = self.skip_empty_sections, - is_method = True, - ).generate_documentation() + '\n\n' + md += ( + PythonDefinitionDocumentationGenerator( + method_or_class, + self.include_sections, + level=self.level + 2, + allow_html=self.allow_html, + allow_tables=self.allow_tables, + skip_empty_sections=self.skip_empty_sections, + is_method=True, + ).generate_documentation() + + '\n\n' + ) if not self.definition.body and not self.skip_empty_sections: md += 'This class does not have a body.' @@ -809,12 +833,12 @@ class PythonDefinitionDocumentationGenerator: return md.strip() def generate_documentation(self) -> str: - ''' + """ Generates the documentation in the markdown format. :return: The documentation. :rtype: str - ''' + """ md = self.level * '#' + ' ' @@ -848,13 +872,13 @@ class PythonDefinitionDocumentationGenerator: md += self._generate_signature_section() + '\n\n' if self.include_sections.returns: - md += self._generate_returns_section() + '\n\n' + md += self._generate_returns_section() + '\n\n' if self.include_sections.params: - md += self._generate_params_section() + '\n\n' + md += self._generate_params_section() + '\n\n' if self.include_sections.exceptions: - md += self._generate_exceptions_section() + '\n\n' + md += self._generate_exceptions_section() + '\n\n' if isinstance(self.definition, PythonClassDefinition): if self.include_sections.bases: @@ -874,8 +898,9 @@ class PythonDefinitionDocumentationGenerator: return md.strip() + class PythonModuleDocumentationGenerator: - ''' + """ A documentation generator for a Python module. :param module_path: The path of the module file. @@ -887,21 +912,21 @@ class PythonModuleDocumentationGenerator: :param include_sections: The sections that will be included. :type include_sections: PythonDefinitionDocumentationIncludeSections :param kwargs: The options for ``PythonDefinitionDocumentationGenerator``. - ''' + """ def __init__( - self, - module_path: pathlib.Path, - src_directory: Union[pathlib.Path, None] = None, - include_sections: PythonDefinitionDocumentationIncludeSections = ( - PythonDefinitionDocumentationIncludeSections() - ), - **kwargs, - ) -> None: + self, + module_path: pathlib.Path, + src_directory: Union[pathlib.Path, None] = None, + include_sections: PythonDefinitionDocumentationIncludeSections = ( + PythonDefinitionDocumentationIncludeSections() + ), + **kwargs, + ) -> None: if module_path.name.count('.') > 1: raise InvalidNamespaceError( 'namespace identifier cannot contain more than one dot', - namespace_identifier = module_path.name, + namespace_identifier=module_path.name, ) self.module_path = pathlib.Path(str(module_path)) @@ -930,25 +955,24 @@ class PythonModuleDocumentationGenerator: return self._ast_cache def collect_definitions(self) -> Iterator[PythonDefinition]: - ''' + """ Collects all function and class definitions of the module. :return: All definitions of the module :rtype: Iterator[PythonDefinition] - ''' + """ tree = self._ast return _collect_definitions(tree) def generate_documentation(self) -> str: - ''' + """ Generates the documentation in the markdown format. :return: The documentation. :rtype: str - ''' - + """ md = '# Module `' @@ -973,26 +997,30 @@ class PythonModuleDocumentationGenerator: md += docstring + '\n\n' for definition in self.collect_definitions(): - md += PythonDefinitionDocumentationGenerator( - definition, - self.include_sections, - 2, - **self.kwargs, - ).generate_documentation() + '\n\n' + md += ( + PythonDefinitionDocumentationGenerator( + definition, + self.include_sections, + 2, + **self.kwargs, + ).generate_documentation() + + '\n\n' + ) return md.strip() + def _generate_package_namespace_documentation( - namespace: PythonPackageNamespace, - documentation_directory: pathlib.Path, - root_directory: pathlib.Path, - dir: pathlib.Path, - include_sections: PythonDefinitionDocumentationIncludeSections = ( - PythonDefinitionDocumentationIncludeSections() - ), - kwargs: dict = {}, - ) -> None: - ''' + namespace: PythonPackageNamespace, + documentation_directory: pathlib.Path, + root_directory: pathlib.Path, + dir: pathlib.Path, + include_sections: PythonDefinitionDocumentationIncludeSections = ( + PythonDefinitionDocumentationIncludeSections() + ), + kwargs: dict = {}, +) -> None: + """ Generates the documentation for a package namespace and writes it to the documentation directory. @@ -1007,19 +1035,20 @@ def _generate_package_namespace_documentation( :param include_sections: The sections to be included in the documentation. :type include_sections: PythonDefinitionDocumentationIncludeSections :param kwargs: The options for the documentation generator. - ''' + """ documentation_directory = pathlib.Path(str(documentation_directory)) for sub_namespace in namespace.sub_namespaces: if isinstance(sub_namespace, PythonPackageNamespace): - ( - documentation_directory / sub_namespace.name - ).mkdir(mode = 0o700, exist_ok = True) + (documentation_directory / sub_namespace.name).mkdir( + mode=0o700, exist_ok=True + ) _generate_package_namespace_documentation( sub_namespace, documentation_directory / sub_namespace.name, - root_directory, dir / sub_namespace.name, + root_directory, + dir / sub_namespace.name, include_sections, kwargs, ) @@ -1035,8 +1064,9 @@ def _generate_package_namespace_documentation( ).generate_documentation() ) + class PythonDocumentationGenerator: - ''' + """ The class for the documentation generator. :param project_directory: The directory of the project. @@ -1046,17 +1076,17 @@ class PythonDocumentationGenerator: :param include_sections: The sections to be included in the documentation. :type include_sections: PythonDefinitionDocumentationIncludeSections :param kwargs: The options for ``PythonDefinitionDocumentationGenerator``. - ''' + """ def __init__( - self, - project_directory: pathlib.Path, - docs_directory: pathlib.Path, - include_sections: PythonDefinitionDocumentationIncludeSections = ( - PythonDefinitionDocumentationIncludeSections() - ), - **kwargs, - ) -> None: + self, + project_directory: pathlib.Path, + docs_directory: pathlib.Path, + include_sections: PythonDefinitionDocumentationIncludeSections = ( + PythonDefinitionDocumentationIncludeSections() + ), + **kwargs, + ) -> None: self.project_directory = pathlib.Path(str(project_directory)) self.docs_directory = pathlib.Path(str(docs_directory)) self.include_sections = include_sections @@ -1074,25 +1104,24 @@ class PythonDocumentationGenerator: return namespace def namespace(self) -> list[PythonPackageNamespace]: - ''' + """ Returns the project as a namespace. :return: The project as a namespace. :rtype: list[PythonPackageNamespace] - ''' + """ src_dir = self.project_directory / 'src' return [ - self._namespace(dir) - for dir in src_dir.iterdir() if dir.is_dir() + self._namespace(dir) for dir in src_dir.iterdir() if dir.is_dir() ] def generate_documentation(self) -> None: - ''' + """ Generates the full project documentation and writes it to the documentation directory. - ''' + """ _generate_package_namespace_documentation( PythonPackageNamespace('src', self.namespace()), diff --git a/src/jcloud_docsgen/core/python/arguments.py b/src/jcloud_docsgen/core/python/arguments.py index 9140fd8..961b5dc 100644 --- a/src/jcloud_docsgen/core/python/arguments.py +++ b/src/jcloud_docsgen/core/python/arguments.py @@ -31,6 +31,7 @@ __all__ = [ 'PythonASTArgumentsListParser', ] + class PythonArgumentKind(Enum): NORMAL = 0 POSITIONAL_ONLY = 1 @@ -38,8 +39,9 @@ class PythonArgumentKind(Enum): VARARG = 3 KWARGS = 4 + class PythonFunctionArgument: - ''' + """ Represents an argument of a Python function. :param name: The name of the argument. @@ -50,7 +52,7 @@ class PythonFunctionArgument: :type default: Union[str, None] :param annotation: The type annotation of the argument. :type annotation: Union[str, None] - ''' + """ def __init__( self, @@ -68,7 +70,7 @@ class PythonFunctionArgument: if not name or not name.isidentifier() or keyword.iskeyword(name): raise InvalidPythonIdentifierError( 'invalid identifier', - identifier = name, + identifier=name, ) # check whether the annotation is a valid annotation @@ -77,7 +79,7 @@ class PythonFunctionArgument: if annotation is not None and not annotation: raise InvalidPythonAnnotationError( 'invalid annotation', - annotation = annotation, + annotation=annotation, ) self.name = name @@ -85,13 +87,17 @@ class PythonFunctionArgument: self.default = default self.annotation = annotation - if self.kind in ( - PythonArgumentKind.VARARG, - PythonArgumentKind.KWARGS, - ) and self.default is not None: + if ( + self.kind + in ( + PythonArgumentKind.VARARG, + PythonArgumentKind.KWARGS, + ) + and self.default is not None + ): raise PythonArgumentStructureError( '* or ** arguments cannot have default values', - definition = self.signature_repr(), + definition=self.signature_repr(), ) def __eq__(self, value: PythonFunctionArgument) -> bool: @@ -105,20 +111,22 @@ class PythonFunctionArgument: ) def __repr__(self) -> str: - return type(self).__name__ + repr(( - self.name, - self.kind, - self.default, - self.annotation, - )) + return type(self).__name__ + repr( + ( + self.name, + self.kind, + self.default, + self.annotation, + ) + ) def signature_repr(self) -> str: - ''' + """ Returns the function signature representation of the argument. :return: The string representation of the argument. :rtype: str - ''' + """ if self.kind == PythonArgumentKind.KWARGS: str_repr = '**' @@ -137,48 +145,44 @@ class PythonFunctionArgument: return str_repr + class PythonASTArgumentsListParser: - ''' + """ A parser for making ``PythonFunctionArgument`` objects from an ``ast.arguments`` arguments list. :param ast_arguments_list: The ``ast.arguments`` arguments list. :type ast_arguments_list: ast.arguments - ''' + """ - def __init__(self, ast_arguments_list: ast.arguments) -> None: + def __init__(self, ast_arguments_list: ast.arguments) -> None: self.ast_arguments_list = ast_arguments_list def to_argument_list(self) -> list[PythonFunctionArgument]: - ''' + """ Converts the AST arguments list to a list of Python function argument objects. :return: The list of Python function argument objects. :rtype: list[PythonFunctionArgument] - ''' + """ defaults = ( [ None - for _ in range(len( - self.ast_arguments_list.posonlyargs + - self.ast_arguments_list.args + - self.ast_arguments_list.kwonlyargs - ) - len( - self.ast_arguments_list.defaults - ) - len( - self.ast_arguments_list.kw_defaults - )) + for _ in range( + len( + self.ast_arguments_list.posonlyargs + + self.ast_arguments_list.args + + self.ast_arguments_list.kwonlyargs + ) + - len(self.ast_arguments_list.defaults) + - len(self.ast_arguments_list.kw_defaults) + ) ] + + [ast.unparse(d) for d in self.ast_arguments_list.defaults] + [ - ast.unparse(d) - for d in self.ast_arguments_list.defaults - ] - + [ - ast.unparse(d) - if d is not None - else None + ast.unparse(d) if d is not None else None for d in self.ast_arguments_list.kw_defaults ] ) diff --git a/src/jcloud_docsgen/core/python/definitions.py b/src/jcloud_docsgen/core/python/definitions.py index f54a98a..7c9ac1d 100644 --- a/src/jcloud_docsgen/core/python/definitions.py +++ b/src/jcloud_docsgen/core/python/definitions.py @@ -29,8 +29,9 @@ __all__ = [ 'PythonClassDefinition', ] + def _python_docstring(doc: Union[str, None]) -> Union[PythonDocstring, None]: - ''' + """ Returns the PythonDocstring object if the docstring is a string and not ``None``. @@ -39,12 +40,13 @@ def _python_docstring(doc: Union[str, None]) -> Union[PythonDocstring, None]: :return: The PythonDocstring object or ``None``. :rtype: Union[PythonDocstring, None] - ''' + """ return PythonDocstring(doc) if doc is not None else None + class PythonDefinition: - ''' + """ A base class for Python definition (a class, function or asynchronous function definition) classes. @@ -57,7 +59,7 @@ class PythonDefinition: :raises InvalidPythonIdentifierError: If the name is not a valid Python identifier. - ''' + """ def __init__( self, @@ -68,7 +70,7 @@ class PythonDefinition: if keyword.iskeyword(name) or not name.isidentifier() or not name: raise InvalidPythonIdentifierError( 'invalid identifier', - identifier = name, + identifier=name, ) assert_that_is_instance(doc, (PythonDocstring, types.NoneType)) @@ -89,12 +91,12 @@ class PythonDefinition: @classmethod def from_node(cls, node: ast.stmt) -> PythonDefinition: - ''' + """ From an AST node. :param node: The AST node. :type node: ast.stmt - ''' + """ return cls( node.name, @@ -107,8 +109,9 @@ class PythonDefinition: return False return self._arg_list() == value._arg_list() + class PythonFunctionDefinition(PythonDefinition): - ''' + """ A PythonDefinition subclass representing a Python function definition. @@ -125,7 +128,7 @@ class PythonFunctionDefinition(PythonDefinition): :raises InvalidPythonIdentifierError: If the name is not a valid Python identifier. - ''' + """ def __init__( self, @@ -150,12 +153,12 @@ class PythonFunctionDefinition(PythonDefinition): @classmethod def from_node(cls, node: ast.stmt) -> PythonFunctionDefinition: - ''' + """ From an AST node. :param node: The AST node. :type node: ast.stmt - ''' + """ return cls( node.name, @@ -165,8 +168,9 @@ class PythonFunctionDefinition(PythonDefinition): [ast.unparse(d) for d in node.decorator_list], ) + class PythonAsyncFunctionDefinition(PythonFunctionDefinition): - ''' + """ A PythonDefinition subclass representing an asynchronous Python function definition. @@ -183,10 +187,11 @@ class PythonAsyncFunctionDefinition(PythonFunctionDefinition): :raises InvalidPythonIdentifierError: If the name is not a valid Python identifier. - ''' + """ + class PythonClassDefinition(PythonDefinition): - ''' + """ A PythonDefinition subclass representing a Python class definition. :param name: The name of the definition. @@ -202,7 +207,7 @@ class PythonClassDefinition(PythonDefinition): :raises InvalidPythonIdentifierError: If the name is not a valid Python identifier. - ''' + """ def __init__( self, @@ -227,12 +232,12 @@ class PythonClassDefinition(PythonDefinition): @classmethod def from_node(cls, node: ast.stmt) -> PythonClassDefinition: - ''' + """ From an AST node. :param node: The AST node. :type node: ast.stmt - ''' + """ return cls( node.name, @@ -242,16 +247,12 @@ class PythonClassDefinition(PythonDefinition): [ PythonFunctionDefinition.from_node(expr) if isinstance(expr, ast.FunctionDef) - else PythonAsyncFunctionDefinition.from_node(expr) if isinstance(expr, ast.AsyncFunctionDef) - else PythonClassDefinition.from_node(expr) - for expr in node.body if isinstance( - expr, - (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef) + expr, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef) ) ], ) diff --git a/src/jcloud_docsgen/core/python/docstrings.py b/src/jcloud_docsgen/core/python/docstrings.py index 6405eab..51c7285 100644 --- a/src/jcloud_docsgen/core/python/docstrings.py +++ b/src/jcloud_docsgen/core/python/docstrings.py @@ -15,17 +15,16 @@ from enum import Enum import docstring_parser -__all__ = [ - 'PythonDocstring' -] +__all__ = ['PythonDocstring'] + class PythonDocstring: - ''' + """ Represents a Python docstring. :param docstring: The docstring as a string. :type docstring: str - ''' + """ def __init__(self, docstring: str) -> None: self.docstring = docstring @@ -39,11 +38,11 @@ class PythonDocstring: return self.docstring == value.docstring def parse(self) -> docstring_parser.Docstring: - ''' + """ Parses the docstring. :return: The parsed docstring. :rtype: docstring_parser.Docstring - ''' + """ return docstring_parser.parse(self.docstring) diff --git a/src/jcloud_docsgen/core/python/namespaces.py b/src/jcloud_docsgen/core/python/namespaces.py index ad3218d..2dc70b7 100644 --- a/src/jcloud_docsgen/core/python/namespaces.py +++ b/src/jcloud_docsgen/core/python/namespaces.py @@ -27,20 +27,22 @@ __all__ = [ 'PythonModuleNamespace', ] + class PythonNamespace: - ''' + """ The base class for all Python namespaces such as modules or packages. :param name: The name of the namespace. :type name: str - ''' + """ + def __init__(self, name: str) -> None: assert_that_is_instance(name, str) if not name.strip(): raise InvalidNamespaceError( 'invalid namespace', - namespace_identifier = name, + namespace_identifier=name, ) self.name = name @@ -48,6 +50,7 @@ class PythonNamespace: def __repr__(self) -> str: return f'{type(self).__name__}({self.name!r})' + PythonPackageNamespaceDictType: TypeAlias = Dict[ str, Union[ @@ -56,15 +59,16 @@ PythonPackageNamespaceDictType: TypeAlias = Dict[ ], ] + class PythonPackageNamespace(PythonNamespace): - ''' + """ A subclass of ``PythonNamespace`` for Python package namespaces. :param name: The name of the namespace. :type name: str :param sub_namespaces: The sub-namespaces. :type sub_namespaces: list[PythonNamespace] - ''' + """ def __init__( self, @@ -78,7 +82,7 @@ class PythonPackageNamespace(PythonNamespace): self._sub_namespaces = sub_namespaces def namespace(self, sub_namespaces: List[str]) -> PythonNamespace: - ''' + """ Returns the namespace object with a specific identifier, such as ``['package', 'subpackage', 'module']``. @@ -91,7 +95,7 @@ class PythonPackageNamespace(PythonNamespace): :return: The namespace. :rtype: PythonNamespace - ''' + """ if not sub_namespaces: raise InvalidNamespaceError('invalid namespace') @@ -115,7 +119,7 @@ class PythonPackageNamespace(PythonNamespace): self, package: PythonPackageNamespace, ) -> PythonPackageNamespaceDictType: - ''' + """ Returns the names of all sub-namespaces of the specified package namespace and keeps the package structure. @@ -124,7 +128,7 @@ class PythonPackageNamespace(PythonNamespace): :return: The names if all sub-namespaces. :rtype: PythonPackageNamespaceDictType - ''' + """ return { sn.name: ( @@ -136,13 +140,13 @@ class PythonPackageNamespace(PythonNamespace): } def sub_namespace_names(self) -> PythonPackageNamespaceDictType: - ''' + """ Returns the names of all sub-namespaces and keeps the package structure. :return: The names if all sub-namespaces. :rtype: PythonPackageNamespaceDictType - ''' + """ return self._sub_namespaces_names(self) @@ -159,7 +163,7 @@ class PythonPackageNamespace(PythonNamespace): return type(self).__name__ + repr((self.name, self._sub_namespaces)) def __getitem__(self, name: str) -> PythonNamespace: - ''' + """ Returns a namespace with the specified name. :param name: The name of the namespace @@ -169,7 +173,7 @@ class PythonPackageNamespace(PythonNamespace): :return: The namespace :rtype: PythonNamespace - ''' + """ for sub in self._sub_namespaces: if sub.name == name: @@ -177,11 +181,11 @@ class PythonPackageNamespace(PythonNamespace): raise NamespaceNotFoundError( 'no such namespace', - namespace_identifier = name, + namespace_identifier=name, ) def add(self, namespace: PythonNamespace) -> None: - ''' + """ Adds a namespace. :param namespace: The namespace to add. @@ -190,12 +194,12 @@ class PythonPackageNamespace(PythonNamespace): :raises NamespaceExistsError: If a namespace with the name of the namespace that is attempted to add already exists. - ''' + """ try: self.__getitem__(namespace.name) raise NamespaceExistsError( 'namespace already exists', - namespace_identifier = namespace.name, + namespace_identifier=namespace.name, ) except NamespaceNotFoundError: self._sub_namespaces.append(namespace) @@ -204,13 +208,14 @@ class PythonPackageNamespace(PythonNamespace): def sub_namespaces(self) -> List[PythonNamespace]: return self._sub_namespaces + class PythonModuleNamespace(PythonNamespace): - ''' + """ A subclass of ``PythonNamespace`` for Python module namespaces. :param name: The name of the namespace. :type name: str - ''' + """ def __init__(self, name: str) -> None: super().__init__(name) diff --git a/src/jcloud_docsgen/exceptions.py b/src/jcloud_docsgen/exceptions.py index ee2b51a..dc81f2e 100644 --- a/src/jcloud_docsgen/exceptions.py +++ b/src/jcloud_docsgen/exceptions.py @@ -12,10 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. + class NamespaceError(ValueError): - ''' + """ Base class for namespace errors. - ''' + """ + def __init__(self, *args: object, namespace_identifier: str = '') -> None: super().__init__(*args) self.namespace_identifier = namespace_identifier @@ -25,23 +27,24 @@ class NamespaceError(ValueError): return '' else: return f'{self.args[0]}{ - ": " - if self.namespace_identifier and self.args[0] - else "" - }{ - self.namespace_identifier - if self.args[0] - else "" - }' + ": " if self.namespace_identifier and self.args[0] else "" + }{self.namespace_identifier if self.args[0] else ""}' + class InvalidNamespaceError(NamespaceError): ... + + class NamespaceNotFoundError(NamespaceError): ... + + class NamespaceExistsError(NamespaceError): ... + class PythonIdentifierError(ValueError): - ''' + """ Base class for Python identifier errors. - ''' + """ + def __init__(self, *args: object, identifier: str = '') -> None: super().__init__(*args) self.identifier = identifier @@ -51,21 +54,18 @@ class PythonIdentifierError(ValueError): return '' else: return f'{self.args[0]}{ - ": " - if self.identifier and self.args[0] - else "" - }{ - self.identifier - if self.args[0] - else "" - }' + ": " if self.identifier and self.args[0] else "" + }{self.identifier if self.args[0] else ""}' + class InvalidPythonIdentifierError(PythonIdentifierError): ... + class PythonAnnotationError(ValueError): - ''' + """ Base class for Python annotation errors. - ''' + """ + def __init__(self, *args: object, annotation: str = '') -> None: super().__init__(*args) self.annotation = annotation @@ -75,21 +75,18 @@ class PythonAnnotationError(ValueError): return '' else: return f'{self.args[0]}{ - ": " - if self.annotation and self.args[0] - else "" - }{ - self.annotation - if self.args[0] - else "" - }' + ": " if self.annotation and self.args[0] else "" + }{self.annotation if self.args[0] else ""}' + class InvalidPythonAnnotationError(PythonAnnotationError): ... + class PythonDefinitionError(ValueError): - ''' + """ Base class for Python definition errors. - ''' + """ + def __init__(self, *args: object, definition: str = '') -> None: super().__init__(*args) self.definition = definition @@ -99,13 +96,8 @@ class PythonDefinitionError(ValueError): return '' else: return f'{self.args[0]}{ - ": " - if self.definition and self.args[0] - else "" - }{ - self.definition - if self.args[0] - else "" - }' + ": " if self.definition and self.args[0] else "" + }{self.definition if self.args[0] else ""}' + class PythonArgumentStructureError(PythonDefinitionError): ... diff --git a/src/jcloud_docsgen/utils.py b/src/jcloud_docsgen/utils.py index d602602..504c180 100644 --- a/src/jcloud_docsgen/utils.py +++ b/src/jcloud_docsgen/utils.py @@ -12,9 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -''' +""" The utilities for jcloud_docsgen -''' +""" import pathlib import os @@ -27,15 +27,17 @@ try: except ImportError: from typing_extensions import deprecated + @deprecated('Use pathlib.Path instead.') class ExistingDirectory(pathlib.Path): - ''' + """ pathlib.Path subclass that is a directory. ExistingDirectory represents a filesystem path but it also checks whether the path exists and is not a file but a directory. It inherits from pathlib.Path. - ''' + """ + def __init__(self, path, *args, **kwargs) -> None: if not os.path.exists(path): raise FileNotFoundError( @@ -47,15 +49,17 @@ class ExistingDirectory(pathlib.Path): raise NotADirectoryError(errno.ENOTDIR, 'not a directory', path) super().__init__(*(path, *args), **kwargs) + @deprecated('Use pathlib.Path instead.') class ExistingFile(pathlib.Path): - ''' + """ pathlib.Path subclass that is a file. ExistingFile represents a filesystem path but it also checks whether the path exists and is not a directory but a file. It inherits from pathlib.Path. - ''' + """ + def __init__(self, path, *args, **kwargs) -> None: if not os.path.exists(path): raise FileNotFoundError( @@ -67,8 +71,9 @@ class ExistingFile(pathlib.Path): raise IsADirectoryError(errno.EISDIR, 'is a directory', path) super().__init__(*(path, *args), **kwargs) + def _quote(string: str, quotation_mark: str) -> str: - ''' + """ Quotes a string. :param string: The string to quote @@ -78,16 +83,17 @@ def _quote(string: str, quotation_mark: str) -> str: :return: The quoted string :rtype: str - ''' + """ return quotation_mark + string + quotation_mark + def human_readable_list( ls: list, final_separator: str = 'and', quotation_mark: str = '', ) -> str: - ''' + """ Generates a human-readable list from a list. :param ls: The list. @@ -101,7 +107,7 @@ def human_readable_list( :return: The human-readable list. :rtype: str - ''' + """ # empty list if not ls: @@ -111,18 +117,26 @@ def human_readable_list( if len(ls) == 1: return _quote(str(ls[0]), quotation_mark) - return ', '.join( - [ - _quote( - str(obj), - quotation_mark - ) # quote the string representation of the object - for obj in ls[:-1] # do not include the last element of the list - ], - ) + ' ' + final_separator + ' ' + _quote(str(ls[-1]), quotation_mark) + return ( + ', '.join( + [ + _quote( + str(obj), quotation_mark + ) # quote the string representation of the object + for obj in ls[ + :-1 + ] # do not include the last element of the list + ], + ) + + ' ' + + final_separator + + ' ' + + _quote(str(ls[-1]), quotation_mark) + ) + def _list_type_names(types: list[type]) -> list[str]: - ''' + """ Converts a list of types into a list of their names (``__name__`` attribute) @@ -131,10 +145,11 @@ def _list_type_names(types: list[type]) -> list[str]: :return: The list of the names of the types :rtype: list[str] - ''' + """ return [tp.__name__ for tp in types] + def assert_that_is_instance( obj: object, class_or_tuple: Union[ @@ -145,8 +160,8 @@ def assert_that_is_instance( ) -> None: if not isinstance(class_or_tuple, Union[type, types.UnionType, tuple]): raise TypeError( - f'class_or_tuple: expected \'Union[type, types.UnionType, ' - f'tuple[type, ...]]\', \'got {type(class_or_tuple).__name__}\'', + f"class_or_tuple: expected 'Union[type, types.UnionType, " + f"tuple[type, ...]]', 'got {type(class_or_tuple).__name__}'", ) if not isinstance(obj, class_or_tuple): if isinstance(class_or_tuple, (tuple, types.UnionType)): @@ -157,18 +172,21 @@ def assert_that_is_instance( else: exception_message_expected = '' exception_message_expected += human_readable_list( - _list_type_names(class_or_tuple), 'or', '\'', + _list_type_names(class_or_tuple), + 'or', + "'", ) else: - exception_message_expected = '\'' + class_or_tuple.__name__ + '\'' + exception_message_expected = "'" + class_or_tuple.__name__ + "'" raise TypeError( - f'expected {exception_message_expected}, got \'{type( - obj - ).__name__}\'', + f"expected {exception_message_expected}, got '{ + type(obj).__name__ + }'", ) + def non_empty_str(value: Union[str, None]) -> Union[str, None]: - ''' + """ Returns the value or ``None``. Returns the value if it is not empty and not `Ǹone``; otherwise, @@ -181,7 +199,7 @@ def non_empty_str(value: Union[str, None]) -> Union[str, None]: :return: The value or ``None``. :rtype: Union[str, None] - ''' + """ if value is None: return None @@ -191,11 +209,12 @@ def non_empty_str(value: Union[str, None]) -> Union[str, None]: return value + def get_relative_path_segments( path: pathlib.Path, root: pathlib.Path, ) -> list[str]: - ''' + """ Returns the path segments relative to ``root``. :param path: The path. @@ -205,7 +224,7 @@ def get_relative_path_segments( :return: The path segments relative to ``root``. :rtype: list[str] - ''' + """ return list( path.resolve() diff --git a/tests/integration/cli/test_cli.py b/tests/integration/cli/test_cli.py index 8e56a32..17a27ec 100644 --- a/tests/integration/cli/test_cli.py +++ b/tests/integration/cli/test_cli.py @@ -15,6 +15,7 @@ import subprocess import sys + def test_cli(): result = subprocess.run( [ @@ -23,12 +24,13 @@ def test_cli(): 'jcloud_docsgen', '--help', ], - capture_output = True, - text = True, + capture_output=True, + text=True, ) stdout = result.stdout.lower() - assert \ - 'usage:' in stdout and \ - 'positional arguments' in stdout and \ - 'options' in stdout and \ - '--help' in stdout + assert ( + 'usage:' in stdout + and 'positional arguments' in stdout + and 'options' in stdout + and '--help' in stdout + ) diff --git a/tests/unit/cli/python_project/project/src/pkg/module.py b/tests/unit/cli/python_project/project/src/pkg/module.py index fd01ebd..3deb2b6 100644 --- a/tests/unit/cli/python_project/project/src/pkg/module.py +++ b/tests/unit/cli/python_project/project/src/pkg/module.py @@ -1,5 +1,5 @@ def f(a: int = 42) -> str: - ''' + """ Does something. :param a: A parameter. @@ -7,5 +7,5 @@ def f(a: int = 42) -> str: :return: A string. :rtype: str - ''' + """ ... diff --git a/tests/unit/cli/test_parser.py b/tests/unit/cli/test_parser.py index 7666e59..9ababcb 100644 --- a/tests/unit/cli/test_parser.py +++ b/tests/unit/cli/test_parser.py @@ -15,20 +15,28 @@ import pytest from jcloud_docsgen.cli.cli import create_argument_parser -@pytest.mark.parametrize('lang', [ - 'javascript', - 'Python', - 'PYTHON', -]) + +@pytest.mark.parametrize( + 'lang', + [ + 'javascript', + 'Python', + 'PYTHON', + ], +) def test_language_error(lang): parser = create_argument_parser() with pytest.raises(SystemExit): parser.parse_args([lang]) -@pytest.mark.parametrize('lang', [ - 'python', -]) + +@pytest.mark.parametrize( + 'lang', + [ + 'python', + ], +) def test_language_success(lang): parser = create_argument_parser() parser.parse_args([lang]) diff --git a/tests/unit/cli/test_python.py b/tests/unit/cli/test_python.py index 9b11ff0..c858770 100644 --- a/tests/unit/cli/test_python.py +++ b/tests/unit/cli/test_python.py @@ -17,152 +17,169 @@ import pytest from jcloud_docsgen.cli.cli import create_argument_parser, main as cli_main from jcloud_docsgen.cli.languages.python import parse_sections_list from jcloud_docsgen.core.python import ( - PythonDefinitionDocumentationIncludeSections + PythonDefinitionDocumentationIncludeSections, ) -@pytest.mark.parametrize('include,exclude,expected', [ - ( - [], - [], - PythonDefinitionDocumentationIncludeSections( - signature = False, - returns = False, - params = False, - exceptions = False, - examples = False, - docstring = False, - bases = False, - decorators = False, - class_body = False, + +@pytest.mark.parametrize( + 'include,exclude,expected', + [ + ( + [], + [], + PythonDefinitionDocumentationIncludeSections( + signature=False, + returns=False, + params=False, + exceptions=False, + examples=False, + docstring=False, + bases=False, + decorators=False, + class_body=False, + ), ), - ), - ( - [], - ['signature'], - PythonDefinitionDocumentationIncludeSections( - signature = False, - returns = False, - params = False, - exceptions = False, - examples = False, - docstring = False, - bases = False, - decorators = False, - class_body = False, + ( + [], + ['signature'], + PythonDefinitionDocumentationIncludeSections( + signature=False, + returns=False, + params=False, + exceptions=False, + examples=False, + docstring=False, + bases=False, + decorators=False, + class_body=False, + ), ), - ), - ( - ['signature'], - ['signature'], - PythonDefinitionDocumentationIncludeSections( - signature = False, - returns = False, - params = False, - exceptions = False, - examples = False, - docstring = False, - bases = False, - decorators = False, - class_body = False, + ( + ['signature'], + ['signature'], + PythonDefinitionDocumentationIncludeSections( + signature=False, + returns=False, + params=False, + exceptions=False, + examples=False, + docstring=False, + bases=False, + decorators=False, + class_body=False, + ), ), - ), - ( - ['signature'], - [], - PythonDefinitionDocumentationIncludeSections( - signature = True, - returns = False, - params = False, - exceptions = False, - examples = False, - docstring = False, - bases = False, - decorators = False, - class_body = False, + ( + ['signature'], + [], + PythonDefinitionDocumentationIncludeSections( + signature=True, + returns=False, + params=False, + exceptions=False, + examples=False, + docstring=False, + bases=False, + decorators=False, + class_body=False, + ), ), - ), - ( - None, - [], - PythonDefinitionDocumentationIncludeSections(), - ), - ( - ['signature', 'exceptions', 'bases', 'class_body'], - ['signature', 'bases'], - PythonDefinitionDocumentationIncludeSections( - signature = False, - returns = False, - params = False, - exceptions = True, - examples = False, - docstring = False, - bases = False, - decorators = False, - class_body = True, + ( + None, + [], + PythonDefinitionDocumentationIncludeSections(), ), - ), - ( - None, - ['params', 'docstring'], - PythonDefinitionDocumentationIncludeSections( - signature = True, - returns = True, - params = False, - exceptions = True, - examples = True, - docstring = False, - bases = True, - decorators = True, - class_body = True, + ( + ['signature', 'exceptions', 'bases', 'class_body'], + ['signature', 'bases'], + PythonDefinitionDocumentationIncludeSections( + signature=False, + returns=False, + params=False, + exceptions=True, + examples=False, + docstring=False, + bases=False, + decorators=False, + class_body=True, + ), ), - ) -]) + ( + None, + ['params', 'docstring'], + PythonDefinitionDocumentationIncludeSections( + signature=True, + returns=True, + params=False, + exceptions=True, + examples=True, + docstring=False, + bases=True, + decorators=True, + class_body=True, + ), + ), + ], +) def test_parse_sections_list(include, exclude, expected): assert parse_sections_list(include, exclude) == expected + def test_sections_error(): parser = create_argument_parser() with pytest.raises(SystemExit): - parser.parse_args([ - 'python', - '-s', - 'param', # correct: `params` - ]) + parser.parse_args( + [ + 'python', + '-s', + 'param', # correct: `params` + ] + ) with pytest.raises(SystemExit): - parser.parse_args([ - 'python', - '-s', - 'params', - 'docstrng', # correct: `docstring` - ]) + parser.parse_args( + [ + 'python', + '-s', + 'params', + 'docstrng', # correct: `docstring` + ] + ) + def test_sections_success(): parser = create_argument_parser() - parser.parse_args([ - 'python', - '-s', - 'params', - ]) - parser.parse_args([ - 'python', - '-s', - 'params', - 'docstring', - ]) + parser.parse_args( + [ + 'python', + '-s', + 'params', + ] + ) + parser.parse_args( + [ + 'python', + '-s', + 'params', + 'docstring', + ] + ) + def test_docs_generation(expectdir): with expectdir('python_project') as output_dir: output_dir: pathlib.Path input_dir = pathlib.Path(__file__).parent / 'python_project/project' - cli_main([ - 'python', - '-s', - 'params', - 'docstring', - '-HTo', - str(output_dir), - str(input_dir), - ]) + cli_main( + [ + 'python', + '-s', + 'params', + 'docstring', + '-HTo', + str(output_dir), + str(input_dir), + ] + ) diff --git a/tests/unit/core/python/_core/test_PythonDefinitionDocumentationGenerator.py b/tests/unit/core/python/_core/test_PythonDefinitionDocumentationGenerator.py index 45d9344..52de56d 100644 --- a/tests/unit/core/python/_core/test_PythonDefinitionDocumentationGenerator.py +++ b/tests/unit/core/python/_core/test_PythonDefinitionDocumentationGenerator.py @@ -28,8 +28,9 @@ from src.jcloud_docsgen.core.python.arguments import ( from src.jcloud_docsgen.core.python.docstrings import PythonDocstring import pytest + def _signature_section(signature: str) -> str: - ''' + """ The definition documentation signature section of the specified signature. @@ -38,218 +39,224 @@ def _signature_section(signature: str) -> str: :return: The definition documentation signature section. :rtype: str - ''' + """ - return f'''## Function signature + return f"""## Function signature ```python {signature} -```''' +```""" -@pytest.mark.parametrize('definition_documentation_generator,expected', [ - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], - ), - ), - 'a()' - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - 'str', - None, - [], - ), - ), - 'a() -> str' - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - 'str', - None, - [], - ), - ), - 'a(a) -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'str', - ), - ], - 'str', - None, - [], - ), - ), - 'a(a: str) -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - '\'42\'', - None, - ) - ], - 'str', - None, - [], - ), - ), - 'a(a = \'42\') -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - '\'42\'', - 'str', - ) - ], - 'str', - None, - [], - ), - ), - 'a(a: str = \'42\') -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - '\'42\'', - 'str', - ) - ], - 'str', - None, - [], - ), - ), - 'a(a: str = \'42\', /) -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ) - ], - 'str', - None, - [], - ), - ), - 'a(a, /) -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ) - ], - None, - None, - [], - ), - ), - 'a(a, /)', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - '__init__', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'definition', - PythonArgumentKind.NORMAL, - None, - 'PythonDefinition', - ), - PythonFunctionArgument( - 'allow_html', - PythonArgumentKind.KEYWORD_ONLY, - 'True', - 'bool', - ), - PythonFunctionArgument( - 'level', - PythonArgumentKind.KEYWORD_ONLY, - '1', - 'int', - ), - ], - 'None', - None, - [], + +@pytest.mark.parametrize( + 'definition_documentation_generator,expected', + [ + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), ), + 'a()', ), ( - '__init__(self, definition: PythonDefinition, *, ' - 'allow_html: bool = True, level: int = 1) -> None' + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + 'str', + None, + [], + ), + ), + 'a() -> str', ), - ), -]) + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + 'str', + None, + [], + ), + ), + 'a(a) -> str', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'str', + ), + ], + 'str', + None, + [], + ), + ), + 'a(a: str) -> str', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + "'42'", + None, + ) + ], + 'str', + None, + [], + ), + ), + "a(a = '42') -> str", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + "'42'", + 'str', + ) + ], + 'str', + None, + [], + ), + ), + "a(a: str = '42') -> str", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + "'42'", + 'str', + ) + ], + 'str', + None, + [], + ), + ), + "a(a: str = '42', /) -> str", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ) + ], + 'str', + None, + [], + ), + ), + 'a(a, /) -> str', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ) + ], + None, + None, + [], + ), + ), + 'a(a, /)', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + '__init__', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'definition', + PythonArgumentKind.NORMAL, + None, + 'PythonDefinition', + ), + PythonFunctionArgument( + 'allow_html', + PythonArgumentKind.KEYWORD_ONLY, + 'True', + 'bool', + ), + PythonFunctionArgument( + 'level', + PythonArgumentKind.KEYWORD_ONLY, + '1', + 'int', + ), + ], + 'None', + None, + [], + ), + ), + ( + '__init__(self, definition: PythonDefinition, *, ' + 'allow_html: bool = True, level: int = 1) -> None' + ), + ), + ], +) def test_PythonDefinitionDocumentationGenerator_generate_signature( definition_documentation_generator, expected, ): assert definition_documentation_generator.generate_signature() == expected + @pytest.mark.parametrize( ( 'definition_documentation_generator,exp' @@ -280,205 +287,209 @@ def test_PythonDefinitionDocumentationGenerator_generate_signature_exceptions( definition_documentation_generator.generate_signature() assert str(exc_info.value) == expected_exception_msg -@pytest.mark.parametrize('definition_documentation_generator,expected', [ - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], - ), - ), - 'a()', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - 'str', - None, - [], - ), - ), - 'a() -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - 'str', - None, - [], - ), - ), - 'a(a) -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'str', - ), - ], - 'str', - None, - [], - ), - ), - 'a(a: str) -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - '\'42\'', - None, - ), - ], - 'str', - None, - [], - ), - ), - 'a(a = \'42\') -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - '\'42\'', - 'str', - ), - ], - 'str', - None, - [], - ), - ), - 'a(a: str = \'42\') -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - '\'42\'', - 'str', - ), - ], - 'str', - None, - [], - ), - ), - 'a(a: str = \'42\', /) -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - ], - 'str', - None, - [], - ), - ), - 'a(a, /) -> str', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - ], - None, - None, - [], - ), - ), - 'a(a, /)', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - '__init__', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'definition', - PythonArgumentKind.NORMAL, - None, - 'PythonDefinition', - ), - PythonFunctionArgument( - 'allow_html', - PythonArgumentKind.KEYWORD_ONLY, - 'True', - 'bool', - ), - PythonFunctionArgument( - 'level', - PythonArgumentKind.KEYWORD_ONLY, - '1', - 'int', - ), - ], - 'None', - None, - [], + +@pytest.mark.parametrize( + 'definition_documentation_generator,expected', + [ + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), ), + 'a()', ), ( - '__init__(self, definition: PythonDefinition, *, ' - 'allow_html: bool = True, level: int = 1) -> None' + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + 'str', + None, + [], + ), + ), + 'a() -> str', ), - ), -]) + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + 'str', + None, + [], + ), + ), + 'a(a) -> str', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'str', + ), + ], + 'str', + None, + [], + ), + ), + 'a(a: str) -> str', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + "'42'", + None, + ), + ], + 'str', + None, + [], + ), + ), + "a(a = '42') -> str", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + "'42'", + 'str', + ), + ], + 'str', + None, + [], + ), + ), + "a(a: str = '42') -> str", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + "'42'", + 'str', + ), + ], + 'str', + None, + [], + ), + ), + "a(a: str = '42', /) -> str", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + ], + 'str', + None, + [], + ), + ), + 'a(a, /) -> str', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + ], + None, + None, + [], + ), + ), + 'a(a, /)', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + '__init__', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'definition', + PythonArgumentKind.NORMAL, + None, + 'PythonDefinition', + ), + PythonFunctionArgument( + 'allow_html', + PythonArgumentKind.KEYWORD_ONLY, + 'True', + 'bool', + ), + PythonFunctionArgument( + 'level', + PythonArgumentKind.KEYWORD_ONLY, + '1', + 'int', + ), + ], + 'None', + None, + [], + ), + ), + ( + '__init__(self, definition: PythonDefinition, *, ' + 'allow_html: bool = True, level: int = 1) -> None' + ), + ), + ], +) def test_PythonDefinitionDocumentationGenerator__generate_signature_section( definition_documentation_generator, expected, @@ -488,253 +499,254 @@ def test_PythonDefinitionDocumentationGenerator__generate_signature_section( == _signature_section(expected) ) -@pytest.mark.parametrize('definition_documentation_generator,expected', [ - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], - ), - allow_html = False, - skip_empty_sections = True, - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(''), - [], - ), - allow_html = False, - skip_empty_sections = True, - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('a'), - [], - ), - allow_html = False, - skip_empty_sections = True, - ), - '## Docstring\n\na', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('a\nb'), - [], - ), - allow_html = False, - skip_empty_sections = True, - ), - '## Docstring\n\na\nb', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], +@pytest.mark.parametrize( + 'definition_documentation_generator,expected', + [ + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), + allow_html=False, + skip_empty_sections=True, ), - allow_html = True, - skip_empty_sections = True, - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(''), - [], - ), - allow_html = True, - skip_empty_sections = True, - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('a'), - [], - ), - allow_html = True, - skip_empty_sections = True, + '', ), ( - '

Docstring

a
' - ), - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('a\nb'), - [], + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(''), + [], + ), + allow_html=False, + skip_empty_sections=True, ), - allow_html = True, - skip_empty_sections = True, + '', ), ( - '

Docstring

a\nb
' - ), - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('a'), + [], + ), + allow_html=False, + skip_empty_sections=True, ), - allow_html = False, - skip_empty_sections = False, - ), - '## Docstring\n\nThere is no docstring to show.', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(''), - [], - ), - allow_html = False, - skip_empty_sections = False, - ), - '## Docstring\n\nThere is no docstring to show.', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('a'), - [], - ), - allow_html = False, - skip_empty_sections = False, - ), - '## Docstring\n\na', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('a\nb'), - [], - ), - allow_html = False, - skip_empty_sections = False, - ), - '## Docstring\n\na\nb', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], - ), - allow_html = True, - skip_empty_sections = False, + '## Docstring\n\na', ), ( - '

Docstring<' - '/h2>

There is no docstring to show.
' - ), - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(''), - [], + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('a\nb'), + [], + ), + allow_html=False, + skip_empty_sections=True, ), - allow_html = True, - skip_empty_sections = False, + '## Docstring\n\na\nb', ), ( - '

Docstring<' - '/h2>

There is no docstring to show.
' - ), - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('a'), - [], + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), + allow_html=True, + skip_empty_sections=True, ), - allow_html = True, - skip_empty_sections = False, + '', ), ( - '

Docstring

a
' - ), - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('a\nb'), - [], + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(''), + [], + ), + allow_html=True, + skip_empty_sections=True, ), - allow_html = True, - skip_empty_sections = False, + '', ), ( - '

Docstring

a\nb
' + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('a'), + [], + ), + allow_html=True, + skip_empty_sections=True, + ), + ( + '

Docstring

a
' + ), ), - ), -]) + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('a\nb'), + [], + ), + allow_html=True, + skip_empty_sections=True, + ), + ( + '

Docstring

a\nb
' + ), + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), + allow_html=False, + skip_empty_sections=False, + ), + '## Docstring\n\nThere is no docstring to show.', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(''), + [], + ), + allow_html=False, + skip_empty_sections=False, + ), + '## Docstring\n\nThere is no docstring to show.', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('a'), + [], + ), + allow_html=False, + skip_empty_sections=False, + ), + '## Docstring\n\na', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('a\nb'), + [], + ), + allow_html=False, + skip_empty_sections=False, + ), + '## Docstring\n\na\nb', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), + allow_html=True, + skip_empty_sections=False, + ), + ( + '

Docstring<' + '/h2>

There is no docstring to show.
' + ), + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(''), + [], + ), + allow_html=True, + skip_empty_sections=False, + ), + ( + '

Docstring<' + '/h2>

There is no docstring to show.
' + ), + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('a'), + [], + ), + allow_html=True, + skip_empty_sections=False, + ), + ( + '

Docstring

a
' + ), + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('a\nb'), + [], + ), + allow_html=True, + skip_empty_sections=False, + ), + ( + '

Docstring

a\nb
' + ), + ), + ], +) def test_PythonDefinitionDocumentationGenerator__generate_docstring_section( definition_documentation_generator, expected, @@ -744,368 +756,366 @@ def test_PythonDefinitionDocumentationGenerator__generate_docstring_section( == expected ) -@pytest.mark.parametrize('definition_documentation_generator,expected', [ - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], - ), - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], - ), - skip_empty_sections = False, - ), - '## Parameters\n\nThis function takes no parameters.', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ) - ], - None, - None, - [], - ), - ), - '''## Parameters - -- Parameter: `a` - - Type: -- - - Kind: normal - - Default value: -- - - Description: --''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - '1', - None, - ) - ], - None, - None, - [], - ), - ), - '''## Parameters - -- Parameter: `a` - - Type: -- - - Kind: normal - - Default value: `1` - - Description: --''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int', - ) - ], - None, - None, - [], - ), - ), - '''## Parameters - -- Parameter: `a` - - Type: `int` - - Kind: normal - - Default value: -- - - Description: --''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - '1', - 'int', - ) - ], - None, - None, - [], - ), - ), - '''## Parameters - -- Parameter: `a` - - Type: `int` - - Kind: normal - - Default value: `1` - - Description: --''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ) - ], - None, - None, - [], - ), - ), - '''## Parameters - -- Parameter: `a` - - Type: -- - - Kind: normal - - Default value: -- - - Description: -- - -- Parameter: `b` - - Type: -- - - Kind: positional-only - - Default value: -- - - Description: --''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - ], - None, - PythonDocstring(':param b: a parameter\n:type b: int'), - [], - ), - ), - '''## Parameters - -- Parameter: `a` - - Type: -- - - Kind: normal - - Default value: -- - - Description: -- - -- Parameter: `b` - - Type: `int` - - Kind: positional-only - - Default value: -- - - Description: a parameter''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - ], - None, - PythonDocstring( - ':param b:\n:type b: int', +@pytest.mark.parametrize( + 'definition_documentation_generator,expected', + [ + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], ), - [], ), - ), '''## Parameters - -- Parameter: `a` - - Type: -- - - Kind: normal - - Default value: -- - - Description: -- - -- Parameter: `b` - - Type: `int` - - Kind: positional-only - - Default value: -- - - Description: --''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - ], - None, - PythonDocstring(':param b: \n:type b: int'), - [], - ), - ), '''## Parameters - -- Parameter: `a` - - Type: -- - - Kind: normal - - Default value: -- - - Description: -- - -- Parameter: `b` - - Type: `int` - - Kind: positional-only - - Default value: -- - - Description: --''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - ], - None, - PythonDocstring(':param b: a parameter\n:type b: int'), - [], - ), - allow_tables = True, + '', ), - '''## Parameters + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), + skip_empty_sections=False, + ), + '## Parameters\n\nThis function takes no parameters.', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ) + ], + None, + None, + [], + ), + ), + """## Parameters + +- Parameter: `a` + + Type: -- + + Kind: normal + + Default value: -- + + Description: --""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + '1', + None, + ) + ], + None, + None, + [], + ), + ), + """## Parameters + +- Parameter: `a` + + Type: -- + + Kind: normal + + Default value: `1` + + Description: --""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int', + ) + ], + None, + None, + [], + ), + ), + """## Parameters + +- Parameter: `a` + + Type: `int` + + Kind: normal + + Default value: -- + + Description: --""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + '1', + 'int', + ) + ], + None, + None, + [], + ), + ), + """## Parameters + +- Parameter: `a` + + Type: `int` + + Kind: normal + + Default value: `1` + + Description: --""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + ], + None, + None, + [], + ), + ), + """## Parameters + +- Parameter: `a` + + Type: -- + + Kind: normal + + Default value: -- + + Description: -- + +- Parameter: `b` + + Type: -- + + Kind: positional-only + + Default value: -- + + Description: --""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + ], + None, + PythonDocstring(':param b: a parameter\n:type b: int'), + [], + ), + ), + """## Parameters + +- Parameter: `a` + + Type: -- + + Kind: normal + + Default value: -- + + Description: -- + +- Parameter: `b` + + Type: `int` + + Kind: positional-only + + Default value: -- + + Description: a parameter""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + ], + None, + PythonDocstring( + ':param b:\n:type b: int', + ), + [], + ), + ), + """## Parameters + +- Parameter: `a` + + Type: -- + + Kind: normal + + Default value: -- + + Description: -- + +- Parameter: `b` + + Type: `int` + + Kind: positional-only + + Default value: -- + + Description: --""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + ], + None, + PythonDocstring(':param b: \n:type b: int'), + [], + ), + ), + """## Parameters + +- Parameter: `a` + + Type: -- + + Kind: normal + + Default value: -- + + Description: -- + +- Parameter: `b` + + Type: `int` + + Kind: positional-only + + Default value: -- + + Description: --""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + ], + None, + PythonDocstring(':param b: a parameter\n:type b: int'), + [], + ), + allow_tables=True, + ), + """## Parameters | Parameter | Type | Kind | Default value | Description | | --- | --- | --- | --- | --- | | `a` | -- | normal | -- | -- | -| `b` | `int` | positional-only | -- | a parameter |''', - ), -]) +| `b` | `int` | positional-only | -- | a parameter |""", + ), + ], +) def test_PythonDefinitionDocumentationGenerator__generate_params_section( definition_documentation_generator, expected, @@ -1115,59 +1125,62 @@ def test_PythonDefinitionDocumentationGenerator__generate_params_section( == expected ) -@pytest.mark.parametrize('definition_documentation_generator,expected', [ - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], + +@pytest.mark.parametrize( + 'definition_documentation_generator,expected', + [ + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), ), + '', ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), + skip_empty_sections=False, ), - skip_empty_sections = False, + '## Exceptions\n\nThis function raises no exceptions.', ), - '## Exceptions\n\nThis function raises no exceptions.', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(':raises E: a'), [], + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(':raises E: a'), + [], + ), ), - ), - '''## Exceptions + """## Exceptions - Exception: `E` - Description: a''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(':raises E:\n:raises E2:'), - [], - ), + Description: a""", ), - '''## Exceptions + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(':raises E:\n:raises E2:'), + [], + ), + ), + """## Exceptions - Exception: `E` @@ -1175,20 +1188,19 @@ def test_PythonDefinitionDocumentationGenerator__generate_params_section( - Exception: `E2` - Description: --''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(':raises E:\n:raises E2: a'), - [], - ), + Description: --""", ), - '''## Exceptions + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(':raises E:\n:raises E2: a'), + [], + ), + ), + """## Exceptions - Exception: `E` @@ -1196,9 +1208,10 @@ def test_PythonDefinitionDocumentationGenerator__generate_params_section( - Exception: `E2` - Description: a''', - ), -]) + Description: a""", + ), + ], +) def test_PythonDefinitionDocumentationGenerator__generate_exceptions_section( definition_documentation_generator, expected, @@ -1208,175 +1221,175 @@ def test_PythonDefinitionDocumentationGenerator__generate_exceptions_section( == expected ) -@pytest.mark.parametrize('definition_documentation_generator,expected', [ - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], - ), - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(''), - [], - ), - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('Examples\n--------'), - [], - ), - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('Examples\n--------\n'), - [], - ), - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('Examples\n--------\n\n'), - [], - ), - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], +@pytest.mark.parametrize( + 'definition_documentation_generator,expected', + [ + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), ), - skip_empty_sections = False + '', ), - '## Examples\n\nThere are no examples.', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(''), - [], + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(''), + [], + ), ), - skip_empty_sections = False, + '', ), - '## Examples\n\nThere are no examples.', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('Examples\n--------'), - [], + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('Examples\n--------'), + [], + ), ), - skip_empty_sections = False, + '', ), - '## Examples\n\nThere are no examples.', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('Examples\n--------\n'), - [], + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('Examples\n--------\n'), + [], + ), ), - skip_empty_sections = False, + '', ), - '## Examples\n\nThere are no examples.', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('Examples\n--------\n\n'), - [], + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('Examples\n--------\n\n'), + [], + ), ), - skip_empty_sections = False, + '', ), - '## Examples\n\nThere are no examples.', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring( - '''Examples + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), + skip_empty_sections=False, + ), + '## Examples\n\nThere are no examples.', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(''), + [], + ), + skip_empty_sections=False, + ), + '## Examples\n\nThere are no examples.', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('Examples\n--------'), + [], + ), + skip_empty_sections=False, + ), + '## Examples\n\nThere are no examples.', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('Examples\n--------\n'), + [], + ), + skip_empty_sections=False, + ), + '## Examples\n\nThere are no examples.', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('Examples\n--------\n\n'), + [], + ), + skip_empty_sections=False, + ), + '## Examples\n\nThere are no examples.', + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring( + """Examples -------- >>> a() -None''', +None""", + ), + [], ), - [], ), - ), - '''## Examples + """## Examples ```python >>> a() -```''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring( - '''Examples +```""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring( + """Examples -------- >>> a() None >>> a() -None''', +None""", + ), + [], ), - [], ), - ), - '''## Examples + """## Examples ```python >>> a() @@ -1386,28 +1399,27 @@ None''', ```python >>> a() -```''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring( - '''Examples +```""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring( + """Examples -------- >>> a() None >>> b() -1''', +1""", + ), + [], ), - [], ), - ), - '''## Examples + """## Examples ```python >>> a() @@ -1417,9 +1429,10 @@ None ```python >>> b() -```''', - ), -]) +```""", + ), + ], +) def test_PythonDefinitionDocumentationGenerator__generate_examples_section( definition_documentation_generator, expected, @@ -1429,105 +1442,104 @@ def test_PythonDefinitionDocumentationGenerator__generate_examples_section( == expected ) -@pytest.mark.parametrize('definition_documentation_generator,expected', [ - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - 'int', - None, - [], + +@pytest.mark.parametrize( + 'definition_documentation_generator,expected', + [ + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + 'int', + None, + [], + ), ), - ), - '''## Returns + """## Returns -Return type: `int`''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - 'int', - PythonDocstring(':return: value'), - [], - ), - ), - '''## Returns - -value - -Return type: `int`''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - 'int', - PythonDocstring(':return: value\n:rtype: str'), - [], - ), - ), - '''## Returns - -value - -Return type: `int`''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(':return: value\n:rtype: str'), - [], - ), - ), - '''## Returns - -value - -Return type: `str`''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring(':return: value'), - [], - ), - ), - '''## Returns - -value''', - ), - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('a'), - [], - ), - skip_empty_sections = False, +Return type: `int`""", ), ( - '## Returns\n\nThis function does not provi' - 'de any information about its return value.' + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + 'int', + PythonDocstring(':return: value'), + [], + ), + ), + """## Returns + +value + +Return type: `int`""", ), - ), -]) + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + 'int', + PythonDocstring(':return: value\n:rtype: str'), + [], + ), + ), + """## Returns + +value + +Return type: `int`""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(':return: value\n:rtype: str'), + [], + ), + ), + """## Returns + +value + +Return type: `str`""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring(':return: value'), + [], + ), + ), + """## Returns + +value""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('a'), + [], + ), + skip_empty_sections=False, + ), + ( + '## Returns\n\nThis function does not provi' + 'de any information about its return value.' + ), + ), + ], +) def test_PythonDefinitionDocumentationGenerator__generate_returns_section( definition_documentation_generator, expected, @@ -1537,18 +1549,21 @@ def test_PythonDefinitionDocumentationGenerator__generate_returns_section( == expected ) -@pytest.mark.parametrize('definition_documentation_generator,expected', [ - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - ['a', 'b'], + +@pytest.mark.parametrize( + 'definition_documentation_generator,expected', + [ + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + ['a', 'b'], + ), ), - ), - '''## Decorators + """## Decorators ```python a @@ -1556,52 +1571,53 @@ a ```python b -```''', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - ['a'], - ), +```""", ), - '''## Decorators + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + ['a'], + ), + ), + """## Decorators ```python a -```''', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], - ), +```""", ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), ), - skip_empty_sections = False, + '', ), - '''## Decorators + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), + skip_empty_sections=False, + ), + """## Decorators -This function or class does not have any decorators.''', - ), -]) +This function or class does not have any decorators.""", + ), + ], +) def test_PythonDefinitionDocumentationGenerator__generate_decorators_section( definition_documentation_generator, expected, @@ -1611,97 +1627,101 @@ def test_PythonDefinitionDocumentationGenerator__generate_decorators_section( == expected ) -@pytest.mark.parametrize('definition_documentation_generator,expected', [ - ( - PythonDefinitionDocumentationGenerator( - PythonClassDefinition( - 'A', - [], - None, - [], - [], - ), - ), - '', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonClassDefinition( - 'A', - [], - None, - [], - [], - ), - skip_empty_sections = False, - ), - '''## Base classes -This class does not have any base classes.''', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonClassDefinition( - 'A', - ['a'], - None, - [], - [], +@pytest.mark.parametrize( + 'definition_documentation_generator,expected', + [ + ( + PythonDefinitionDocumentationGenerator( + PythonClassDefinition( + 'A', + [], + None, + [], + [], + ), ), - skip_empty_sections = False, + '', ), - '''## Base classes + ( + PythonDefinitionDocumentationGenerator( + PythonClassDefinition( + 'A', + [], + None, + [], + [], + ), + skip_empty_sections=False, + ), + """## Base classes -- `a`''', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonClassDefinition( - 'A', - ['b'], - None, - [], - [], - ), - skip_empty_sections = False, +This class does not have any base classes.""", ), - '''## Base classes + ( + PythonDefinitionDocumentationGenerator( + PythonClassDefinition( + 'A', + ['a'], + None, + [], + [], + ), + skip_empty_sections=False, + ), + """## Base classes -- `b`''', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonClassDefinition( - 'A', - ['a', 'b'], - None, - [], - [], - ), - skip_empty_sections = False, +- `a`""", ), - '''## Base classes + ( + PythonDefinitionDocumentationGenerator( + PythonClassDefinition( + 'A', + ['b'], + None, + [], + [], + ), + skip_empty_sections=False, + ), + """## Base classes + +- `b`""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonClassDefinition( + 'A', + ['a', 'b'], + None, + [], + [], + ), + skip_empty_sections=False, + ), + """## Base classes - `a` -- `b`''', - ), - ( - PythonDefinitionDocumentationGenerator( - PythonClassDefinition( - 'A', - ['b', 'a'], - None, - [], - [], - ), - skip_empty_sections = False, +- `b`""", ), - '''## Base classes + ( + PythonDefinitionDocumentationGenerator( + PythonClassDefinition( + 'A', + ['b', 'a'], + None, + [], + [], + ), + skip_empty_sections=False, + ), + """## Base classes - `b` -- `a`''', - ), -]) +- `a`""", + ), + ], +) def test_PythonDefinitionDocumentationGenerator__generate_bases_section( definition_documentation_generator, expected, @@ -1711,40 +1731,43 @@ def test_PythonDefinitionDocumentationGenerator__generate_bases_section( == expected ) -@pytest.mark.parametrize('definition_documentation_generator,expected', [ - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'hello', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'world', - PythonArgumentKind.NORMAL, - '1', - None, - ), - PythonFunctionArgument( - 'something', - PythonArgumentKind.KEYWORD_ONLY, - '\'something\'', - 'str', - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - 'bool', - PythonDocstring( - '''A function. + +@pytest.mark.parametrize( + 'definition_documentation_generator,expected', + [ + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'hello', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'world', + PythonArgumentKind.NORMAL, + '1', + None, + ), + PythonFunctionArgument( + 'something', + PythonArgumentKind.KEYWORD_ONLY, + "'something'", + 'str', + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + 'bool', + PythonDocstring( + """A function. Very long ... @@ -1757,13 +1780,13 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list''', +:rtype: list""", + ), + ['decorate(1, 2, 3)'], ), - ['decorate(1, 2, 3)'], + allow_html=False, ), - allow_html = False, - ), - '''# Function `a` + """# Function `a` A function. @@ -1852,43 +1875,41 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list''', - ), - - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'hello', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'world', - PythonArgumentKind.NORMAL, - '1', - None, - ), - PythonFunctionArgument( - 'something', - PythonArgumentKind.KEYWORD_ONLY, - '\'something\'', - 'str', - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - 'bool', - PythonDocstring( - '''A function. +:rtype: list""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'hello', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'world', + PythonArgumentKind.NORMAL, + '1', + None, + ), + PythonFunctionArgument( + 'something', + PythonArgumentKind.KEYWORD_ONLY, + "'something'", + 'str', + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + 'bool', + PythonDocstring( + """A function. Very long ... @@ -1901,13 +1922,13 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list''', +:rtype: list""", + ), + ['decorate(1, 2, 3)'], ), - ['decorate(1, 2, 3)'], ), - ), - ( - '''# Function `a` + ( + """# Function `a` A function. @@ -1981,8 +2002,8 @@ decorate(1, 2, 3) -

Docstring

A ''' - '''function. +

Docstring

A """ + """function. Very long ... @@ -1995,64 +2016,62 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list
''' - ), - ), - - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'hello', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'world', - PythonArgumentKind.NORMAL, - '1', - None, - ), - PythonFunctionArgument( - 'something', - PythonArgumentKind.KEYWORD_ONLY, - '\'something\'', - 'str', - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - 'bool', - PythonDocstring( - '''A function. - -Very long ... - -:param hello: A parameter. -:type hello: str -:param something: Something. -:param value: The value. -:type value: object - -:raises ValueError: If the value is invalid. - -:return: The return value. -:rtype: list''', - ), - ['decorate(1, 2, 3)'], +:rtype: list
""" ), - allow_html = False, - allow_tables = True, ), - '''# Function `a` + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'hello', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'world', + PythonArgumentKind.NORMAL, + '1', + None, + ), + PythonFunctionArgument( + 'something', + PythonArgumentKind.KEYWORD_ONLY, + "'something'", + 'str', + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + 'bool', + PythonDocstring( + """A function. + +Very long ... + +:param hello: A parameter. +:type hello: str +:param something: Something. +:param value: The value. +:type value: object + +:raises ValueError: If the value is invalid. + +:return: The return value. +:rtype: list""", + ), + ['decorate(1, 2, 3)'], + ), + allow_html=False, + allow_tables=True, + ), + """# Function `a` A function. @@ -2108,43 +2127,41 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list''', - ), - - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'hello', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'world', - PythonArgumentKind.NORMAL, - '1', - None, - ), - PythonFunctionArgument( - 'something', - PythonArgumentKind.KEYWORD_ONLY, - '\'something\'', - 'str', - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - 'bool', - PythonDocstring( - '''A function. +:rtype: list""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'hello', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'world', + PythonArgumentKind.NORMAL, + '1', + None, + ), + PythonFunctionArgument( + 'something', + PythonArgumentKind.KEYWORD_ONLY, + "'something'", + 'str', + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + 'bool', + PythonDocstring( + """A function. Very long ... @@ -2157,14 +2174,14 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list''', +:rtype: list""", + ), + ['decorate(1, 2, 3)'], ), - ['decorate(1, 2, 3)'], + allow_tables=True, ), - allow_tables = True, - ), - ( - '''# Function `a` + ( + """# Function `a` A function. @@ -2205,8 +2222,8 @@ decorate(1, 2, 3) -

Docstring

A ''' - '''function. +

Docstring

A """ + """function. Very long ... @@ -2219,64 +2236,62 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list
''' - ), - ), - - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'hello', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'world', - PythonArgumentKind.NORMAL, - '1', - None, - ), - PythonFunctionArgument( - 'something', - PythonArgumentKind.KEYWORD_ONLY, - '\'something\'', - 'str', - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - 'bool', - PythonDocstring( - '''A function. - -Very long ... - -:param hello: A parameter. -:type hello: str -:param something: Something. -:param value: The value. -:type value: object - -:raises ValueError: If the value is invalid. - -:return: The return value. -:rtype: list''', - ), - ['decorate(1, 2, 3)'], +:rtype: list
""" ), - allow_html = False, - skip_empty_sections = False, ), - '''# Function `a` + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'hello', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'world', + PythonArgumentKind.NORMAL, + '1', + None, + ), + PythonFunctionArgument( + 'something', + PythonArgumentKind.KEYWORD_ONLY, + "'something'", + 'str', + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + 'bool', + PythonDocstring( + """A function. + +Very long ... + +:param hello: A parameter. +:type hello: str +:param something: Something. +:param value: The value. +:type value: object + +:raises ValueError: If the value is invalid. + +:return: The return value. +:rtype: list""", + ), + ['decorate(1, 2, 3)'], + ), + allow_html=False, + skip_empty_sections=False, + ), + """# Function `a` A function. @@ -2367,43 +2382,41 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list''', - ), - - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'hello', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'world', - PythonArgumentKind.NORMAL, - '1', - None, - ), - PythonFunctionArgument( - 'something', - PythonArgumentKind.KEYWORD_ONLY, - '\'something\'', - 'str', - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - 'bool', - PythonDocstring( - '''A function. +:rtype: list""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'hello', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'world', + PythonArgumentKind.NORMAL, + '1', + None, + ), + PythonFunctionArgument( + 'something', + PythonArgumentKind.KEYWORD_ONLY, + "'something'", + 'str', + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + 'bool', + PythonDocstring( + """A function. Very long ... @@ -2416,14 +2429,14 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list''', +:rtype: list""", + ), + ['decorate(1, 2, 3)'], ), - ['decorate(1, 2, 3)'], + skip_empty_sections=False, ), - skip_empty_sections = False, - ), - ( - '''# Function `a` + ( + """# Function `a` A function. @@ -2499,8 +2512,8 @@ decorate(1, 2, 3) There are no examples. -

Docstring

A ''' - '''function. +

Docstring

A """ + """function. Very long ... @@ -2513,65 +2526,63 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list
''' - ), - ), - - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'hello', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'world', - PythonArgumentKind.NORMAL, - '1', - None, - ), - PythonFunctionArgument( - 'something', - PythonArgumentKind.KEYWORD_ONLY, - '\'something\'', - 'str', - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - 'bool', - PythonDocstring( - '''A function. - -Very long ... - -:param hello: A parameter. -:type hello: str -:param something: Something. -:param value: The value. -:type value: object - -:raises ValueError: If the value is invalid. - -:return: The return value. -:rtype: list''', - ), - ['decorate(1, 2, 3)'], +:rtype: list
""" ), - allow_html = False, - allow_tables = True, - skip_empty_sections = False, ), - '''# Function `a` + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'hello', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'world', + PythonArgumentKind.NORMAL, + '1', + None, + ), + PythonFunctionArgument( + 'something', + PythonArgumentKind.KEYWORD_ONLY, + "'something'", + 'str', + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + 'bool', + PythonDocstring( + """A function. + +Very long ... + +:param hello: A parameter. +:type hello: str +:param something: Something. +:param value: The value. +:type value: object + +:raises ValueError: If the value is invalid. + +:return: The return value. +:rtype: list""", + ), + ['decorate(1, 2, 3)'], + ), + allow_html=False, + allow_tables=True, + skip_empty_sections=False, + ), + """# Function `a` A function. @@ -2629,43 +2640,41 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list''', - ), - - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'hello', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'world', - PythonArgumentKind.NORMAL, - '1', - None, - ), - PythonFunctionArgument( - 'something', - PythonArgumentKind.KEYWORD_ONLY, - '\'something\'', - 'str', - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - 'bool', - PythonDocstring( - '''A function. +:rtype: list""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'hello', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'world', + PythonArgumentKind.NORMAL, + '1', + None, + ), + PythonFunctionArgument( + 'something', + PythonArgumentKind.KEYWORD_ONLY, + "'something'", + 'str', + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + 'bool', + PythonDocstring( + """A function. Very long ... @@ -2678,15 +2687,15 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list''', +:rtype: list""", + ), + ['decorate(1, 2, 3)'], ), - ['decorate(1, 2, 3)'], + allow_tables=True, + skip_empty_sections=False, ), - allow_tables = True, - skip_empty_sections = False, - ), - ( - '''# Function `a` + ( + """# Function `a` A function. @@ -2729,8 +2738,8 @@ decorate(1, 2, 3) There are no examples. -

Docstring

A ''' - '''function. +

Docstring

A """ + """function. Very long ... @@ -2743,44 +2752,42 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list
''' +:rtype: list
""" + ), ), - ), - - - ( - PythonDefinitionDocumentationGenerator( - PythonFunctionDefinition( - 'a', - [ - PythonFunctionArgument( - 'hello', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'world', - PythonArgumentKind.NORMAL, - '1', - None, - ), - PythonFunctionArgument( - 'something', - PythonArgumentKind.KEYWORD_ONLY, - '\'something\'', - 'str', - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - 'bool', - PythonDocstring( - '''A function. + ( + PythonDefinitionDocumentationGenerator( + PythonFunctionDefinition( + 'a', + [ + PythonFunctionArgument( + 'hello', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'world', + PythonArgumentKind.NORMAL, + '1', + None, + ), + PythonFunctionArgument( + 'something', + PythonArgumentKind.KEYWORD_ONLY, + "'something'", + 'str', + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + 'bool', + PythonDocstring( + """A function. Very long ... @@ -2793,126 +2800,124 @@ Very long ... :raises ValueError: If the value is invalid. :return: The return value. -:rtype: list''', +:rtype: list""", + ), + ['decorate(1, 2, 3)'], ), - ['decorate(1, 2, 3)'], + PythonDefinitionDocumentationIncludeSections( + signature=False, + returns=False, + params=False, + exceptions=False, + examples=False, + docstring=False, + bases=False, + decorators=False, + ), + allow_tables=True, + skip_empty_sections=False, ), - PythonDefinitionDocumentationIncludeSections( - signature = False, - returns = False, - params = False, - exceptions = False, - examples = False, - docstring = False, - bases = False, - decorators = False, - ), - allow_tables = True, - skip_empty_sections = False, - ), - '''# Function `a` + """# Function `a` A function. -Very long ...''', - ), - - - ( - PythonDefinitionDocumentationGenerator( - PythonClassDefinition( - 'A', - ['Base1', 'Base2'], - PythonDocstring( - '''A class. +Very long ...""", + ), + ( + PythonDefinitionDocumentationGenerator( + PythonClassDefinition( + 'A', + ['Base1', 'Base2'], + PythonDocstring( + """A class. Examples -------- >>> A() ->>> A()''', +>>> A()""", + ), + ['dec', 'ora', 'tor'], + [ + PythonFunctionDefinition( + '__init__', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + None, + None, + [], + ), + PythonFunctionDefinition( + 'method', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + '1', + 'int', + ), + ], + 'str', + None, + ['decorator'], + ), + PythonAsyncFunctionDefinition( + 'method2', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + None, + None, + [], + ), + PythonClassDefinition( + 'B', + ['Base'], + None, + [], + [ + PythonFunctionDefinition( + '__init__', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ) + ], + None, + None, + [], + ), + ], + ), + ], + ), + allow_html=False, + allow_tables=True, + include_sections=PythonDefinitionDocumentationIncludeSections( + bases=False, ), - ['dec', 'ora', 'tor'], - [ - PythonFunctionDefinition( - '__init__', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - None, - None, - [], - ), - PythonFunctionDefinition( - 'method', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - '1', - 'int', - ), - ], - 'str', - None, - ['decorator'], - ), - PythonAsyncFunctionDefinition( - 'method2', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - None, - None, - [], - ), - PythonClassDefinition( - 'B', - ['Base'], - None, - [], - [ - PythonFunctionDefinition( - '__init__', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ) - ], - None, - None, - [], - ), - ], - ), - ], ), - allow_html = False, - allow_tables = True, - include_sections = PythonDefinitionDocumentationIncludeSections( - bases = False, - ), - ), - '''# Class `A` + """# Class `A` A class. @@ -3032,14 +3037,14 @@ Examples -------- >>> A() ->>> A()''', - ), -]) +>>> A()""", + ), + ], +) def test_PythonDefinitionDocumentationGenerator_generate_documentation( definition_documentation_generator, expected, ): assert ( - definition_documentation_generator.generate_documentation() - == expected + definition_documentation_generator.generate_documentation() == expected ) diff --git a/tests/unit/core/python/_core/test_PythonDocumentationGenerator.py b/tests/unit/core/python/_core/test_PythonDocumentationGenerator.py index e94a613..047da87 100644 --- a/tests/unit/core/python/_core/test_PythonDocumentationGenerator.py +++ b/tests/unit/core/python/_core/test_PythonDocumentationGenerator.py @@ -20,78 +20,82 @@ from src.jcloud_docsgen.core.python.namespaces import ( import pytest import pathlib -@pytest.mark.parametrize('python_documentation_generator,expected', [ - ( - PythonDocumentationGenerator( - pathlib.Path( - 'tests/unit/core/python/_core/test_project_dirs/pdir_1' - ), - pathlib.Path( - 'tests/unit/core/python/_core/test_project_dirs/pdir_1/docs' + +@pytest.mark.parametrize( + 'python_documentation_generator,expected', + [ + ( + PythonDocumentationGenerator( + pathlib.Path( + 'tests/unit/core/python/_core/test_project_dirs/pdir_1' + ), + pathlib.Path( + 'tests/unit/core/python/_core/test_project_dirs/pdir_1/docs' + ), ), + [], ), - [], - ), - ( - PythonDocumentationGenerator( - pathlib.Path( - 'tests/unit/core/python/_core/test_project_dirs/pdir_2' - ), - pathlib.Path( - 'tests/unit/core/python/_core/test_project_dirs/pdir_2/docs' + ( + PythonDocumentationGenerator( + pathlib.Path( + 'tests/unit/core/python/_core/test_project_dirs/pdir_2' + ), + pathlib.Path( + 'tests/unit/core/python/_core/test_project_dirs/pdir_2/docs' + ), ), + [ + PythonPackageNamespace( + 'pkg', + [PythonModuleNamespace('module')], + ), + ], ), - [ - PythonPackageNamespace( - 'pkg', - [ - PythonModuleNamespace('module') - ], - ), - ], - ), - ( - PythonDocumentationGenerator( - pathlib.Path( - 'tests/unit/core/python/_core/test_project_dirs/pdir_3' - ), - pathlib.Path( - 'tests/unit/core/python/_core/test_project_dirs/pdir_3/docs' + ( + PythonDocumentationGenerator( + pathlib.Path( + 'tests/unit/core/python/_core/test_project_dirs/pdir_3' + ), + pathlib.Path( + 'tests/unit/core/python/_core/test_project_dirs/pdir_3/docs' + ), ), + [ + PythonPackageNamespace( + 'pkg', + [ + PythonModuleNamespace('module'), + PythonPackageNamespace( + 'pkg', + [ + PythonModuleNamespace('module2'), + ], + ), + ], + ), + ], ), - [ - PythonPackageNamespace( - 'pkg', - [ - PythonModuleNamespace('module'), - PythonPackageNamespace( - 'pkg', - [ - PythonModuleNamespace( - 'module2' - ), - ], - ), - ], - ), - ], - ), -]) + ], +) def test_PythonDocumentationGenerator_collect_modules( python_documentation_generator: PythonDocumentationGenerator, expected, ): assert python_documentation_generator.namespace() == expected -@pytest.mark.parametrize('dir', [ - d.name - for d in pathlib.Path( - ( - 'tests/unit/core/python/_core/test_PythonDocume' - 'ntationGenerator/test_generate_documentation/' - ), - ).iterdir() -]) + +@pytest.mark.parametrize( + 'dir', + [ + d.name + for d in pathlib.Path( + ( + 'tests/unit/core/python/_core/test_PythonDocume' + 'ntationGenerator/test_generate_documentation/' + ), + ).iterdir() + ], +) def test_generate_documentation(dir, expectdir): with expectdir( 'test_PythonDocumentationGenerator/test_generate_documentation/' + dir @@ -104,12 +108,12 @@ def test_generate_documentation(dir, expectdir): 'tests/unit/core/python/_core/test_PythonDocume' 'ntationGenerator/test_generate_documentation/' ), - ) / - dir / - 'project', + ) + / dir + / 'project', ), ), pathlib.Path(str(d)), - allow_tables = True, - allow_html = False, - ).generate_documentation() # simplify the tests + allow_tables=True, + allow_html=False, + ).generate_documentation() # simplify the tests diff --git a/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/exceptions.py b/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/exceptions.py index 6d29928..bce8c8c 100644 --- a/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/exceptions.py +++ b/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/exceptions.py @@ -1,8 +1,10 @@ class UserNotFoundError(Exception): """User does not exist.""" + pass class InvalidEmailError(Exception): """Email address is invalid.""" - pass \ No newline at end of file + + pass diff --git a/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/models.py b/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/models.py index 1f7cc5f..bf4d0c9 100644 --- a/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/models.py +++ b/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/models.py @@ -7,7 +7,8 @@ class User: """ Represents a user. """ + id: str name: str email: str - age: Optional[int] = None \ No newline at end of file + age: Optional[int] = None diff --git a/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/service.py b/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/service.py index 755c0d8..c240ac8 100644 --- a/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/service.py +++ b/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/service.py @@ -13,23 +13,16 @@ class UserService: self.storage = storage def create_user( - self, - user_id: str, - name: str, - email: str, - age: int | None = None + self, user_id: str, name: str, email: str, age: int | None = None ) -> User: """ Creates and stores a new user. """ if not is_valid_email(email): - raise InvalidEmailError(f"Invalid email: {email}") + raise InvalidEmailError(f'Invalid email: {email}') user = User( - id=user_id, - name=normalize_name(name), - email=email, - age=age + id=user_id, name=normalize_name(name), email=email, age=age ) self.storage.add(user) @@ -51,4 +44,4 @@ class UserService: try: self.storage.delete(user_id) except KeyError: - raise UserNotFoundError(user_id) \ No newline at end of file + raise UserNotFoundError(user_id) diff --git a/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/storage.py b/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/storage.py index 29ff61d..659c14f 100644 --- a/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/storage.py +++ b/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/storage.py @@ -25,4 +25,4 @@ class InMemoryUserStorage: def list_all(self) -> List[User]: """Returns all users.""" - return list(self._users.values()) \ No newline at end of file + return list(self._users.values()) diff --git a/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/utils.py b/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/utils.py index 5ca8309..c0b334a 100644 --- a/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/utils.py +++ b/tests/unit/core/python/_core/test_PythonDocumentationGenerator/test_generate_documentation/case03/project/src/user_management/utils.py @@ -5,7 +5,7 @@ def is_valid_email(email: str) -> bool: """ Checks whether an email address is valid. """ - pattern = r"^[\w\.-]+@[\w\.-]+\.\w+$" + pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$' return re.match(pattern, email) is not None @@ -13,4 +13,4 @@ def normalize_name(name: str) -> str: """ Removes extra spaces and formats the name. """ - return " ".join(name.strip().split()).title() \ No newline at end of file + return ' '.join(name.strip().split()).title() diff --git a/tests/unit/core/python/_core/test_PythonModuleDocumentationGenerator.py b/tests/unit/core/python/_core/test_PythonModuleDocumentationGenerator.py index de6ee92..66d9b33 100644 --- a/tests/unit/core/python/_core/test_PythonModuleDocumentationGenerator.py +++ b/tests/unit/core/python/_core/test_PythonModuleDocumentationGenerator.py @@ -17,6 +17,7 @@ from src.jcloud_docsgen.exceptions import InvalidNamespaceError import pathlib import pytest + @pytest.mark.parametrize( 'module_path,src_directory,expected_exception,expected_exception_msg', [ @@ -216,22 +217,25 @@ def test_PythonModuleDocumentationGenerator_exceptions( PythonModuleDocumentationGenerator(module_path, src_directory) assert str(exc_info.value) == expected_exception_msg -@pytest.mark.parametrize('module_documentation_generator,expected', [ - ( - PythonModuleDocumentationGenerator( - pathlib.Path( - ( - 'tests/unit/core/python/_core/test_pr' - 'oject_dirs/pdir_2/src/pkg/module.py' + +@pytest.mark.parametrize( + 'module_documentation_generator,expected', + [ + ( + PythonModuleDocumentationGenerator( + pathlib.Path( + ( + 'tests/unit/core/python/_core/test_pr' + 'oject_dirs/pdir_2/src/pkg/module.py' + ), ), + pathlib.Path( + 'tests/unit/core/python/_core/test_project_dirs/pdir_2/src/' + ), + allow_tables=True, + allow_html=False, ), - pathlib.Path( - 'tests/unit/core/python/_core/test_project_dirs/pdir_2/src/' - ), - allow_tables = True, - allow_html = False, - ), - '''# Module `pkg.module` + """# Module `pkg.module` A test module. @@ -398,205 +402,21 @@ Barks. ### Docstring -A dog.''' - ), - - ( - PythonModuleDocumentationGenerator( - pathlib.Path( - ( - 'tests/unit/core/python/_core/test_pr' - 'oject_dirs/pdir_2/src/pkg/module.py' - ), - ), - None, - allow_tables = True, - allow_html = False, - ), - '''# Module `module` - -A test module. - -## Function `add` - -Adds two numbers. - - -### Function signature - -```python -add(a: int | float, b: int | float) -> int | float -``` - -### Returns - -The sum. - -Return type: `int | float` - -### Parameters - -| Parameter | Type | Kind | Default value | Description | -| --- | --- | --- | --- | --- | -| `a` | `int | float` | normal | -- | The first number. | -| `b` | `int | float` | normal | -- | The second number. | - - - - - - - -### Docstring - -Adds two numbers. - -:param a: The first number. -:type a: int | float -:param b: The second number. -:type b: int | float - -:return: The sum. -:rtype: int | float - -## Class `Animal` - -A class representing an animal. - - - - -### Body - -#### Constructor (method `__init__`) - -##### Method signature - -```python -__init__(self, name: str) -> None -``` - -##### Returns - -Return type: `None` - -##### Parameters - -| Parameter | Type | Kind | Default value | Description | -| --- | --- | --- | --- | --- | -| `self` | -- | normal | -- | -- | -| `name` | `str` | normal | -- | -- | - -#### Method `greet` - -Returns a greeting. - - -##### Method signature - -```python -greet(self) -``` - -##### Returns - -The greeting. - -Return type: `str` - -##### Parameters - -| Parameter | Type | Kind | Default value | Description | -| --- | --- | --- | --- | --- | -| `self` | -- | normal | -- | -- | - - - - - - - -##### Docstring - -Returns a greeting. - -:return: The greeting. -:rtype: str - - - - - -### Docstring - -A class representing an animal. - -:param name: Its name. -:type name: str - -## Class `Dog` - -A dog. - -### Base classes - -- `Animal` - -### Body - -#### Method `bark` - -Barks. - -##### Method signature - -```python -bark(self) -> None -``` - -##### Returns - -Return type: `None` - -##### Parameters - -| Parameter | Type | Kind | Default value | Description | -| --- | --- | --- | --- | --- | -| `self` | -- | normal | -- | -- | - - - - - - - -##### Docstring - -Barks. - - - - - -### Docstring - -A dog.''' - ), - - ( - PythonModuleDocumentationGenerator( - pathlib.Path( - ( - 'tests/unit/core/python/_core/test_pr' - 'oject_dirs/pdir_2/src/pkg/module.py' - ), - ), - None, - allow_tables = True, - allow_html = True, +A dog.""", ), ( - '''# Module `module` + PythonModuleDocumentationGenerator( + pathlib.Path( + ( + 'tests/unit/core/python/_core/test_pr' + 'oject_dirs/pdir_2/src/pkg/module.py' + ), + ), + None, + allow_tables=True, + allow_html=False, + ), + """# Module `module` A test module. @@ -630,8 +450,190 @@ Return type: `int | float` -

Docstring

Adds ''' - '''two numbers. +### Docstring + +Adds two numbers. + +:param a: The first number. +:type a: int | float +:param b: The second number. +:type b: int | float + +:return: The sum. +:rtype: int | float + +## Class `Animal` + +A class representing an animal. + + + + +### Body + +#### Constructor (method `__init__`) + +##### Method signature + +```python +__init__(self, name: str) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | +| `name` | `str` | normal | -- | -- | + +#### Method `greet` + +Returns a greeting. + + +##### Method signature + +```python +greet(self) +``` + +##### Returns + +The greeting. + +Return type: `str` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | + + + + + + + +##### Docstring + +Returns a greeting. + +:return: The greeting. +:rtype: str + + + + + +### Docstring + +A class representing an animal. + +:param name: Its name. +:type name: str + +## Class `Dog` + +A dog. + +### Base classes + +- `Animal` + +### Body + +#### Method `bark` + +Barks. + +##### Method signature + +```python +bark(self) -> None +``` + +##### Returns + +Return type: `None` + +##### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `self` | -- | normal | -- | -- | + + + + + + + +##### Docstring + +Barks. + + + + + +### Docstring + +A dog.""", + ), + ( + PythonModuleDocumentationGenerator( + pathlib.Path( + ( + 'tests/unit/core/python/_core/test_pr' + 'oject_dirs/pdir_2/src/pkg/module.py' + ), + ), + None, + allow_tables=True, + allow_html=True, + ), + ( + """# Module `module` + +A test module. + +## Function `add` + +Adds two numbers. + + +### Function signature + +```python +add(a: int | float, b: int | float) -> int | float +``` + +### Returns + +The sum. + +Return type: `int | float` + +### Parameters + +| Parameter | Type | Kind | Default value | Description | +| --- | --- | --- | --- | --- | +| `a` | `int | float` | normal | -- | The first number. | +| `b` | `int | float` | normal | -- | The second number. | + + + + + + + +

Docstring

Adds """ + """two numbers. :param a: The first number. :type a: int | float @@ -698,8 +700,8 @@ Return type: `str` -
Docstring
''' - '''Returns a greeting. +
Docstring
""" + """Returns a greeting. :return: The greeting. :rtype: str
@@ -708,8 +710,8 @@ Return type: `str` -

Docstring

A ''' - '''class representing an animal. +

Docstring

A """ + """class representing an animal. :param name: Its name. :type name: str
@@ -750,32 +752,31 @@ Return type: `None` -
Docstring
Barks.''' - '''
+
Docstring
Barks.""" + """
-

Docstring

A dog.''' - '
' - ), - ), - - ( - PythonModuleDocumentationGenerator( - pathlib.Path( - ( - 'tests/unit/core/python/_core/test_pr' - 'oject_dirs/pdir_2/src/pkg/module.py' - ), +

Docstring

A dog.""" + '
' ), - None, - allow_tables = False, - allow_html = True, ), ( - '''# Module `module` + PythonModuleDocumentationGenerator( + pathlib.Path( + ( + 'tests/unit/core/python/_core/test_pr' + 'oject_dirs/pdir_2/src/pkg/module.py' + ), + ), + None, + allow_tables=False, + allow_html=True, + ), + ( + """# Module `module` A test module. @@ -824,8 +825,8 @@ Return type: `int | float` -

Docstring

Adds ''' - '''two numbers. +

Docstring

Adds """ + """two numbers. :param a: The first number. :type a: int | float @@ -913,8 +914,8 @@ Return type: `str` -
Docstring
''' - '''Returns a greeting. +
Docstring
""" + """Returns a greeting. :return: The greeting. :rtype: str
@@ -923,8 +924,8 @@ Return type: `str` -

Docstring

A ''' - '''class representing an animal. +

Docstring

A """ + """class representing an animal. :param name: Its name. :type name: str
@@ -971,31 +972,30 @@ Return type: `None` -
Docstring
Barks.''' - '''
+
Docstring
Barks.""" + """
-

Docstring

A ''' - 'dog.
' - ), - ), - - ( - PythonModuleDocumentationGenerator( - pathlib.Path( - ( - 'tests/unit/core/python/_core/test_pr' - 'oject_dirs/pdir_2/src/pkg/module.py' - ), +

Docstring

A """ + 'dog.
' ), - None, - allow_tables = False, - allow_html = False, ), - '''# Module `module` + ( + PythonModuleDocumentationGenerator( + pathlib.Path( + ( + 'tests/unit/core/python/_core/test_pr' + 'oject_dirs/pdir_2/src/pkg/module.py' + ), + ), + None, + allow_tables=False, + allow_html=False, + ), + """# Module `module` A test module. @@ -1204,9 +1204,10 @@ Barks. ### Docstring -A dog.''' - ), -]) +A dog.""", + ), + ], +) def test_PythonModuleDocumentationGenerator_exceptions( module_documentation_generator, expected, diff --git a/tests/unit/core/python/_core/test__argument_kind_human_readable.py b/tests/unit/core/python/_core/test__argument_kind_human_readable.py index 9100105..cd34bae 100644 --- a/tests/unit/core/python/_core/test__argument_kind_human_readable.py +++ b/tests/unit/core/python/_core/test__argument_kind_human_readable.py @@ -16,12 +16,16 @@ from src.jcloud_docsgen.core.python._core import _argument_kind_human_readable from src.jcloud_docsgen.core.python.arguments import PythonArgumentKind import pytest -@pytest.mark.parametrize('argument_kind,expected', [ - (PythonArgumentKind.NORMAL, 'normal'), - (PythonArgumentKind.POSITIONAL_ONLY, 'positional-only'), - (PythonArgumentKind.KEYWORD_ONLY, 'keyword-only'), - (PythonArgumentKind.VARARG, 'vararg'), - (PythonArgumentKind.KWARGS, 'kwargs'), -]) + +@pytest.mark.parametrize( + 'argument_kind,expected', + [ + (PythonArgumentKind.NORMAL, 'normal'), + (PythonArgumentKind.POSITIONAL_ONLY, 'positional-only'), + (PythonArgumentKind.KEYWORD_ONLY, 'keyword-only'), + (PythonArgumentKind.VARARG, 'vararg'), + (PythonArgumentKind.KWARGS, 'kwargs'), + ], +) def test__argument_kind_human_readable(argument_kind, expected): assert _argument_kind_human_readable(argument_kind) == expected diff --git a/tests/unit/core/python/_core/test__collect_definitions.py b/tests/unit/core/python/_core/test__collect_definitions.py index 56e3b6e..780694a 100644 --- a/tests/unit/core/python/_core/test__collect_definitions.py +++ b/tests/unit/core/python/_core/test__collect_definitions.py @@ -25,8 +25,9 @@ from src.jcloud_docsgen.core.python.docstrings import PythonDocstring import pytest import ast + def module(source_code: str) -> ast.Module: - ''' + """ Returns an AST module of the source code. :param source_code: The module source code. @@ -34,38 +35,41 @@ def module(source_code: str) -> ast.Module: :return: The AST module. :rtype: ast.Module - ''' + """ return ast.parse(source_code) -@pytest.mark.parametrize('module,expected', [ - ( - module('def add(a, b):\n\treturn a + b'), - [ - PythonFunctionDefinition( - 'add', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - None, - None, - [], - ), - ], - ), - ( - module('''def add(a: int | float, b: int | float) -> int | float: + +@pytest.mark.parametrize( + 'module,expected', + [ + ( + module('def add(a, b):\n\treturn a + b'), + [ + PythonFunctionDefinition( + 'add', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + None, + None, + [], + ), + ], + ), + ( + module('''def add(a: int | float, b: int | float) -> int | float: """Adds two numbers.""" return a + b @@ -89,87 +93,87 @@ class Something: """ return self._value '''), - [ - PythonFunctionDefinition( - 'add', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int | float', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - 'int | float', - ), - ], - 'int | float', - PythonDocstring('Adds two numbers.'), - [], - ), - PythonClassDefinition( - 'Something', - [], - PythonDocstring('A class.'), - [], - [ - PythonFunctionDefinition( - '__init__', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.NORMAL, - '42', - 'typing.Any', - ), - ], - 'None', - None, - [], - ), - PythonFunctionDefinition( - 'value', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - 'typing.Any', - PythonDocstring('The value.'), - ['property'], - ), - PythonFunctionDefinition( - 'get_value', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - 'typing.Any', - PythonDocstring('Returns the value.'), - [], - ), - ], - ), - ], - ), - ( - module('''from src.jcloud_docsgen.core.python import ( + [ + PythonFunctionDefinition( + 'add', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int | float', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + 'int | float', + ), + ], + 'int | float', + PythonDocstring('Adds two numbers.'), + [], + ), + PythonClassDefinition( + 'Something', + [], + PythonDocstring('A class.'), + [], + [ + PythonFunctionDefinition( + '__init__', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.NORMAL, + '42', + 'typing.Any', + ), + ], + 'None', + None, + [], + ), + PythonFunctionDefinition( + 'value', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + 'typing.Any', + PythonDocstring('The value.'), + ['property'], + ), + PythonFunctionDefinition( + 'get_value', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + 'typing.Any', + PythonDocstring('Returns the value.'), + [], + ), + ], + ), + ], + ), + ( + module("""from src.jcloud_docsgen.core.python import ( PythonDocumentationGenerator ) from src.jcloud_docsgen.core.python.namespaces import ( @@ -235,139 +239,142 @@ def test_PythonDocumentationGenerator_collect_modules( python_documentation_generator: PythonDocumentationGenerator, expected ): - assert python_documentation_generator.namespace() == expected'''), - [ - PythonFunctionDefinition( - 'test_PythonDocumentationGenerator_type_exceptions', - [ - PythonFunctionArgument( - 'project_directory', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'docs_directory', - PythonArgumentKind.NORMAL, - None, - None, - ) - ], - None, - None, - [ - ( - '''pytest.mark.parametrize('project_directo''' - '''ry,docs_directory', [(1, 1), (1, None), ''' - '''(42, None), (pathlib.Path('tests'), 1), ''' - '''(pathlib.Path('tests/'), 1), (1, pathlib''' - '''.Path('tests/')), (1, pathlib.Path('test''' - '''s')), (None, pathlib.Path('tests'))])''' - ), - ], - ), - PythonFunctionDefinition( - 'test_PythonDocumentationGenerator_collect_modules', - [ - PythonFunctionArgument( - 'python_documentation_generator', - PythonArgumentKind.NORMAL, - None, - 'PythonDocumentationGenerator', - ), - PythonFunctionArgument( - 'expected', - PythonArgumentKind.NORMAL, - None, - None, - ) - ], - None, - None, - [( - '''pytest.mark.parametrize('python_documentation_gener''' - '''ator,expected', [(PythonDocumentationGenerator(path''' - '''lib.Path('tests/unit/core/python/_core/test_project''' - '''_dirs/pdir_1'), pathlib.Path('tests/unit/core/pytho''' - '''n/_core/test_project_dirs/pdir_1/docs')), []), (Pyt''' - '''honDocumentationGenerator(pathlib.Path('tests/unit/''' - '''core/python/_core/test_project_dirs/pdir_2'), pathl''' - '''ib.Path('tests/unit/core/python/_core/test_project_''' - '''dirs/pdir_2/docs')), [PythonPackageNamespace('pkg',''' - ''' [PythonModuleNamespace('module')])]), (PythonDocum''' - '''entationGenerator(pathlib.Path('tests/unit/core/pyt''' - '''hon/_core/test_project_dirs/pdir_3'), pathlib.Path(''' - ''''tests/unit/core/python/_core/test_project_dirs/pdi''' - '''r_3/docs')), [PythonPackageNamespace('pkg', [Python''' - '''ModuleNamespace(\'module'), PythonPackageNamespace(''' - '''\'pkg\', [PythonModuleNamespace(\'module2')])])])])''' - )], - ), - ], - ), - ( - module( - '''class C1: + assert python_documentation_generator.namespace() == expected"""), + [ + PythonFunctionDefinition( + 'test_PythonDocumentationGenerator_type_exceptions', + [ + PythonFunctionArgument( + 'project_directory', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'docs_directory', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + None, + None, + [ + ( + """pytest.mark.parametrize('project_directo""" + """ry,docs_directory', [(1, 1), (1, None), """ + """(42, None), (pathlib.Path('tests'), 1), """ + """(pathlib.Path('tests/'), 1), (1, pathlib""" + """.Path('tests/')), (1, pathlib.Path('test""" + """s')), (None, pathlib.Path('tests'))])""" + ), + ], + ), + PythonFunctionDefinition( + 'test_PythonDocumentationGenerator_collect_modules', + [ + PythonFunctionArgument( + 'python_documentation_generator', + PythonArgumentKind.NORMAL, + None, + 'PythonDocumentationGenerator', + ), + PythonFunctionArgument( + 'expected', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + None, + None, + [ + ( + """pytest.mark.parametrize('python_documentation_gener""" + """ator,expected', [(PythonDocumentationGenerator(path""" + """lib.Path('tests/unit/core/python/_core/test_project""" + """_dirs/pdir_1'), pathlib.Path('tests/unit/core/pytho""" + """n/_core/test_project_dirs/pdir_1/docs')), []), (Pyt""" + """honDocumentationGenerator(pathlib.Path('tests/unit/""" + """core/python/_core/test_project_dirs/pdir_2'), pathl""" + """ib.Path('tests/unit/core/python/_core/test_project_""" + """dirs/pdir_2/docs')), [PythonPackageNamespace('pkg',""" + """ [PythonModuleNamespace('module')])]), (PythonDocum""" + """entationGenerator(pathlib.Path('tests/unit/core/pyt""" + """hon/_core/test_project_dirs/pdir_3'), pathlib.Path(""" + """'tests/unit/core/python/_core/test_project_dirs/pdi""" + """r_3/docs')), [PythonPackageNamespace('pkg', [Python""" + """ModuleNamespace(\'module'), PythonPackageNamespace(""" + """\'pkg\', [PythonModuleNamespace(\'module2')])])])])""" + ) + ], + ), + ], + ), + ( + module( + """class C1: class C2: class C3: def function(self, value: bool, /, arg) -> bool: def should_be_not_in_the_result(arg: int) -> object: pass - return not value''' - ), - [ - PythonClassDefinition( - 'C1', - [], - None, - [], - [ - PythonClassDefinition( - 'C2', - [], - None, - [], - [ - PythonClassDefinition( - 'C3', - [], - None, - [], - [ - PythonFunctionDefinition( - 'function', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'bool', - ), - PythonFunctionArgument( - 'arg', - PythonArgumentKind.NORMAL, - None, - None, - ) - ], - 'bool', - None, - [], - ), - ], - ), - ], - ), - ], + return not value""" ), - ], - ), -]) + [ + PythonClassDefinition( + 'C1', + [], + None, + [], + [ + PythonClassDefinition( + 'C2', + [], + None, + [], + [ + PythonClassDefinition( + 'C3', + [], + None, + [], + [ + PythonFunctionDefinition( + 'function', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'bool', + ), + PythonFunctionArgument( + 'arg', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + 'bool', + None, + [], + ), + ], + ), + ], + ), + ], + ), + ], + ), + ], +) def test___collect_definitions(module, expected): assert list(_collect_definitions(module)) == expected diff --git a/tests/unit/core/python/_core/test__fit_row_length.py b/tests/unit/core/python/_core/test__fit_row_length.py index 9981799..50686d8 100644 --- a/tests/unit/core/python/_core/test__fit_row_length.py +++ b/tests/unit/core/python/_core/test__fit_row_length.py @@ -15,41 +15,50 @@ from src.jcloud_docsgen.core.python._core import _fit_row_length import pytest -@pytest.mark.parametrize('expected_length,row,expected', [ - (0, (), ()), - (1, (), (None,)), - (2, (), (None, None)), - (2, (1,), (1, None)), - (0, (1,), ()), - (1, (1, 2), (1,)), - (1, (1, 2), (1,)), - (0, (1, 2), ()), - (0, (1, 2, 3), ()), - (1, (1, 2, 3), (1,)), - (2, (1, 2, 3), (1, 2)), - - (1, (1,), (1,)), - (2, (1, 1), (1, 1)), - (2, (1, 2), (1, 2)), - (3, (1, 2, 3), (1, 2, 3)), -]) +@pytest.mark.parametrize( + 'expected_length,row,expected', + [ + (0, (), ()), + (1, (), (None,)), + (2, (), (None, None)), + (2, (1,), (1, None)), + (0, (1,), ()), + (1, (1, 2), (1,)), + (1, (1, 2), (1,)), + (0, (1, 2), ()), + (0, (1, 2, 3), ()), + (1, (1, 2, 3), (1,)), + (2, (1, 2, 3), (1, 2)), + (1, (1,), (1,)), + (2, (1, 1), (1, 1)), + (2, (1, 2), (1, 2)), + (3, (1, 2, 3), (1, 2, 3)), + ], +) def test__fit_row_length(expected_length, row, expected): assert _fit_row_length(expected_length, row) == expected -@pytest.mark.parametrize('row', [ - (), - (1,), - (1, 2), - (1, 2, 3), - (1, 2, 3, 456), -]) -@pytest.mark.parametrize('expected_length,expected_exception', [ - (-1, ValueError), - (-2, ValueError), - (-3, ValueError), - (-42, ValueError), -]) + +@pytest.mark.parametrize( + 'row', + [ + (), + (1,), + (1, 2), + (1, 2, 3), + (1, 2, 3, 456), + ], +) +@pytest.mark.parametrize( + 'expected_length,expected_exception', + [ + (-1, ValueError), + (-2, ValueError), + (-3, ValueError), + (-42, ValueError), + ], +) def test__fit_row_length_exceptions(expected_length, row, expected_exception): with pytest.raises(expected_exception) as exc_info: _fit_row_length(expected_length, row) diff --git a/tests/unit/core/python/_core/test__function_params_info.py b/tests/unit/core/python/_core/test__function_params_info.py index 014b4cd..825d998 100644 --- a/tests/unit/core/python/_core/test__function_params_info.py +++ b/tests/unit/core/python/_core/test__function_params_info.py @@ -23,10 +23,11 @@ from src.jcloud_docsgen.core.python.arguments import ( import pytest import docstring_parser + def docstring_args_list( docstring: str, ) -> list[docstring_parser.DocstringParam]: - ''' + """ Returns the parameter list of a docstring. :param docstring: The docstring @@ -34,82 +35,164 @@ def docstring_args_list( :return: The parameter list. :rtype: list[docstring_parser.DocstringParam] - ''' + """ return docstring_parser.parse(docstring).params -@pytest.mark.parametrize('arg_list,docstring,expected', [ - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', 'int'), - ], ':param a: a\n:type a: str', { - 'a': _FunctionParamInfo('int', 'a'), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', None), - ], ':param a: a\n:type a: str', { - 'a': _FunctionParamInfo('str', 'a'), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', None), - PythonFunctionArgument('b', PythonArgumentKind.NORMAL, '', None), - ], ':param a: a\n:type a: str', { - 'a': _FunctionParamInfo('str', 'a'), - 'b': _FunctionParamInfo(None, None), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', None), - PythonFunctionArgument('b', PythonArgumentKind.NORMAL, '', 'int'), - ], ':param a: a\n:type a: str', { - 'a': _FunctionParamInfo('str', 'a'), - 'b': _FunctionParamInfo('int', None), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', None), - PythonFunctionArgument('b', PythonArgumentKind.NORMAL, '', 'int'), - ], ':param a: a\n:type a: str\n:param b: b\n:type b: str', { - 'a': _FunctionParamInfo('str', 'a'), - 'b': _FunctionParamInfo('int', 'b'), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', None), - ], ':param a: a\n:type a: str\n:param b: b\n:type b: int', { - 'a': _FunctionParamInfo('str', 'a'), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', None), - ], '', { - 'a': _FunctionParamInfo(None, None), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', 'str'), - ], '', { - 'a': _FunctionParamInfo('str', None), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', 'str'), - ], ':param a:\n:type a: int', { - 'a': _FunctionParamInfo('str', ''), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', None), - ], ':param a:\n:type a: int', { - 'a': _FunctionParamInfo('int', ''), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', None), - ], ':param a: a', { - 'a': _FunctionParamInfo(None, 'a'), - }), - ([ - PythonFunctionArgument('a', PythonArgumentKind.NORMAL, '', 'str'), - ], ':param a: a', { - 'a': _FunctionParamInfo('str', 'a'), - }), - ([], ':param a: a\n:type a: str', {}), - ([], '', {}), -]) + +@pytest.mark.parametrize( + 'arg_list,docstring,expected', + [ + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', 'int' + ), + ], + ':param a: a\n:type a: str', + { + 'a': _FunctionParamInfo('int', 'a'), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', None + ), + ], + ':param a: a\n:type a: str', + { + 'a': _FunctionParamInfo('str', 'a'), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', None + ), + PythonFunctionArgument( + 'b', PythonArgumentKind.NORMAL, '', None + ), + ], + ':param a: a\n:type a: str', + { + 'a': _FunctionParamInfo('str', 'a'), + 'b': _FunctionParamInfo(None, None), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', None + ), + PythonFunctionArgument( + 'b', PythonArgumentKind.NORMAL, '', 'int' + ), + ], + ':param a: a\n:type a: str', + { + 'a': _FunctionParamInfo('str', 'a'), + 'b': _FunctionParamInfo('int', None), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', None + ), + PythonFunctionArgument( + 'b', PythonArgumentKind.NORMAL, '', 'int' + ), + ], + ':param a: a\n:type a: str\n:param b: b\n:type b: str', + { + 'a': _FunctionParamInfo('str', 'a'), + 'b': _FunctionParamInfo('int', 'b'), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', None + ), + ], + ':param a: a\n:type a: str\n:param b: b\n:type b: int', + { + 'a': _FunctionParamInfo('str', 'a'), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', None + ), + ], + '', + { + 'a': _FunctionParamInfo(None, None), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', 'str' + ), + ], + '', + { + 'a': _FunctionParamInfo('str', None), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', 'str' + ), + ], + ':param a:\n:type a: int', + { + 'a': _FunctionParamInfo('str', ''), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', None + ), + ], + ':param a:\n:type a: int', + { + 'a': _FunctionParamInfo('int', ''), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', None + ), + ], + ':param a: a', + { + 'a': _FunctionParamInfo(None, 'a'), + }, + ), + ( + [ + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, '', 'str' + ), + ], + ':param a: a', + { + 'a': _FunctionParamInfo('str', 'a'), + }, + ), + ([], ':param a: a\n:type a: str', {}), + ([], '', {}), + ], +) def test__function_params_types(arg_list, docstring, expected): - assert _function_params_info( - arg_list, - docstring_args_list(docstring) - ) == expected + assert ( + _function_params_info(arg_list, docstring_args_list(docstring)) + == expected + ) diff --git a/tests/unit/core/python/_core/test__markdown_table.py b/tests/unit/core/python/_core/test__markdown_table.py index 90b49b4..ac99ec1 100644 --- a/tests/unit/core/python/_core/test__markdown_table.py +++ b/tests/unit/core/python/_core/test__markdown_table.py @@ -15,6 +15,7 @@ from src.jcloud_docsgen.core.python._core import _markdown_table import pytest + @pytest.mark.parametrize( ( 'header,body,allow_markdown_table,force_row_le' @@ -55,9 +56,9 @@ import pytest False, True, '--', - '''| a | + """| a | | --- | -| 1 |''', +| 1 |""", ), ( ['a'], @@ -66,9 +67,9 @@ import pytest False, True, '--', - '''| a | + """| a | | --- | -| 1 |''', +| 1 |""", ), ( ['a', 'b'], @@ -77,9 +78,9 @@ import pytest False, True, '--', - '''| a | b | + """| a | b | | --- | --- | -| 1 | 2 |''', +| 1 | 2 |""", ), ( ['a', 'b'], @@ -88,9 +89,9 @@ import pytest False, True, '--', - '''| a | b | + """| a | b | | --- | --- | -| 1 | -- |''', +| 1 | -- |""", ), ( ['a', 'b'], @@ -99,9 +100,9 @@ import pytest False, True, '--', - '''| a | b | + """| a | b | | --- | --- | -| -- | -- |''', +| -- | -- |""", ), ( ['a', 'b'], @@ -110,10 +111,10 @@ import pytest False, True, '--', - '''| a | b | + """| a | b | | --- | --- | | 1 | 2 | -| 3 | 4 |''', +| 3 | 4 |""", ), ( ['a'], @@ -122,9 +123,9 @@ import pytest False, True, '--', - '''| a | + """| a | | --- | -| line1 line2 |''', +| line1 line2 |""", ), ( ['a'], @@ -133,11 +134,10 @@ import pytest False, False, '--', - '''| a | + """| a | | --- | -| line1\nline2 |''', +| line1\nline2 |""", ), - ( [], [], @@ -190,9 +190,9 @@ import pytest False, True, '--', - '''- a: 1 + """- a: 1 - b: 2''', + b: 2""", ), ( ['a', 'b'], @@ -201,9 +201,9 @@ import pytest False, True, '--', - '''- a: 1 + """- a: 1 - b: --''', + b: --""", ), ( ['a', 'b'], @@ -212,9 +212,9 @@ import pytest False, True, '--', - '''- a: -- + """- a: -- - b: --''', + b: --""", ), ( ['a', 'b'], @@ -223,13 +223,13 @@ import pytest False, True, '--', - '''- a: 1 + """- a: 1 b: 2 - a: 3 - b: 4''', + b: 4""", ), ( ['a'], @@ -260,14 +260,18 @@ def test__markdown_table( missing_value, expected, ): - assert _markdown_table( - header, - body, - allow_markdown_table = allow_markdown_table, - force_row_lengths = force_row_lengths, - one_line_values = one_line_values, - missing_value = missing_value, - ) == expected + assert ( + _markdown_table( + header, + body, + allow_markdown_table=allow_markdown_table, + force_row_lengths=force_row_lengths, + one_line_values=one_line_values, + missing_value=missing_value, + ) + == expected + ) + @pytest.mark.parametrize( ( @@ -335,7 +339,6 @@ def test__markdown_table( ValueError, 'expected 2 values, got 3', ), - ( ['a'], [(1, 2)], @@ -412,9 +415,9 @@ def test__markdown_table_exceptions( _markdown_table( header, body, - allow_markdown_table = allow_markdown_table, - force_row_lengths = force_row_lengths, - one_line_values = one_line_values, - missing_value = missing_value, + allow_markdown_table=allow_markdown_table, + force_row_lengths=force_row_lengths, + one_line_values=one_line_values, + missing_value=missing_value, ) assert str(exc_info.value) == expected_exception_msg diff --git a/tests/unit/core/python/_core/test__signature_argument_list.py b/tests/unit/core/python/_core/test__signature_argument_list.py index b586e4b..485c6ef 100644 --- a/tests/unit/core/python/_core/test__signature_argument_list.py +++ b/tests/unit/core/python/_core/test__signature_argument_list.py @@ -19,266 +19,328 @@ from src.jcloud_docsgen.core.python.arguments import ( ) import pytest -@pytest.mark.parametrize('argument_list,expected', [ - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, + +@pytest.mark.parametrize( + 'argument_list,expected', + [ + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + ['a'], ), - ], ['a']), - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + ], + ['a', '/'], ), - ], ['a', '/']), - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + ['a', '/', 'b'], ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + ], + ['a', '/', 'b', '*', 'c'], ), - ], ['a', '/', 'b']), - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, + ( + [ + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + ], + ['b', '*', 'c'], ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, + ( + [ + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + ], + ['*', 'c'], ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, + ( + [ + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + ], + ['b', '/', '*', 'c'], ), - ], ['a', '/', 'b', '*', 'c']), - ([ - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, + ( + [ + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ) + ], + ['*args'], ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + ], + ['a', '*args'], ), - ], ['b', '*', 'c']), - ([ - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + ], + ['a', '/', '*args'], ), - ], ['*', 'c']), - ([ - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, + ( + [ + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'a', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + ], + ['*args', 'a'], ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, + ( + [ + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ['*args', '**kwargs'], ), - ], ['b', '/', '*', 'c']), - ([ - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ) - ], ['*args']), - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ['a', '/', '*args', '**kwargs'], ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ['a', '*args', '**kwargs'], ), - ], ['a', '*args']), - ([ - PythonFunctionArgument( - 'a', PythonArgumentKind.POSITIONAL_ONLY, - None, - None, + ( + [ + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'a', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ['*args', 'a', '**kwargs'], ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ['*', 'a', '**kwargs'], ), - ], ['a', '/', '*args']), - ([ - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ['a', '**kwargs'], ), - PythonFunctionArgument( - 'a', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ['a', '/', '**kwargs'], ), - ], ['*args', 'a']), - ([ - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, + ( + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + '1', + 'int', + ), + ], + ['a: int = 1'], ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], ['*args', '**kwargs']), - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], ['a', '/', '*args', '**kwargs']), - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], ['a', '*args', '**kwargs']), - ([ - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'a', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], ['*args', 'a', '**kwargs']), - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], ['*', 'a', '**kwargs']), - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], ['a', '**kwargs']), - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], ['a', '/', '**kwargs']), - ([ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - '1', - 'int', - ), - ], ['a: int = 1']), -]) + ], +) def test__signature_argument_list(argument_list, expected): assert _signature_argument_list(argument_list) == expected diff --git a/tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py b/tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py index b44f01e..7da0ee4 100644 --- a/tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py +++ b/tests/unit/core/python/_core/test_project_dirs/pdir_2/src/pkg/module.py @@ -1,9 +1,10 @@ -''' +""" A test module. -''' +""" + def add(a: int | float, b: int | float) -> int | float: - ''' + """ Adds two numbers. :param a: The first number. @@ -13,38 +14,41 @@ def add(a: int | float, b: int | float) -> int | float: :return: The sum. :rtype: int | float - ''' + """ return a + b + class Animal: - ''' + """ A class representing an animal. :param name: Its name. :type name: str - ''' + """ + def __init__(self, name: str) -> None: self.name = name def greet(self): - ''' + """ Returns a greeting. :return: The greeting. :rtype: str - ''' + """ return f'Hi there! My name is {self.name}' + class Dog(Animal): - ''' + """ A dog. - ''' + """ def bark(self) -> None: - ''' + """ Barks. - ''' + """ print('Woof!') diff --git a/tests/unit/core/python/arguments/test_PythonASTArgumentsListParser.py b/tests/unit/core/python/arguments/test_PythonASTArgumentsListParser.py index 2b1a8b8..bb11dec 100644 --- a/tests/unit/core/python/arguments/test_PythonASTArgumentsListParser.py +++ b/tests/unit/core/python/arguments/test_PythonASTArgumentsListParser.py @@ -20,8 +20,9 @@ from src.jcloud_docsgen.core.python.arguments import ( import pytest import ast + def argument_list(argument_list: str) -> ast.arguments: - ''' + """ Returns an AST argument list from the argument list source code :param argument_list: The argument list. @@ -29,916 +30,922 @@ def argument_list(argument_list: str) -> ast.arguments: :return: The AST argument list. :rtype: ast.arguments - ''' + """ return ast.parse('def func(' + argument_list + '): ...').body[0].args -@pytest.mark.parametrize('ast_arguments_list,expected', [ - ( - argument_list('a'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - ), - ( - argument_list('a: str'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'str', - ), - ], - ), - ( - argument_list('a: str | int'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'str | int', - ), - ], - ), - ( - argument_list('a: str, b'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'str', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - ), - ( - argument_list('a: str, b: int'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'str', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - ], - ), - ( - argument_list('a, b: int'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - ], - ), - ( - argument_list('a, b, *args'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - ], - ), - ( - argument_list('a: int, b, *args'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - ], - ), - ( - argument_list('a, b: str, *args'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - 'str', - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - ], - ), - ( - argument_list('a: int, b: str, *args'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - 'str', - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - ], - ), - ( - argument_list('a: int, b: str, *args: float'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - 'str', - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - 'float', - ), - ], - ), - ( - argument_list('a: int, b, *args: float'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - 'float', - ), - ], - ), - ( - argument_list('a: int, *args: float'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - 'float', - ), - ], - ), - ( - argument_list('a: int, /, **kwargs'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list('a: int, **kwargs: str'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - 'str', - ), - ], - ), - ( - argument_list('a: int, /, b, **kwargs'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list('a: int, /, b'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - ), - ( - argument_list('a: int, /, b, *, c'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - ], - ), - ( - argument_list('a, b, *, c'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - ], - ), - ( - argument_list('a, b, *args, c'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - ], - ), - ( - argument_list('a, b, *args, c, **kwargs'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list('a, b, /, *, c, **kwargs'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list('a, b, /, c, *, d, **kwargs'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'd', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list( - ( - 'a: str, b: int, /, c: float, d: list,' - ' *, e: tuple, f: dict, **kwargs: set' - ), + +@pytest.mark.parametrize( + 'ast_arguments_list,expected', + [ + ( + argument_list('a'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], ), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'str', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.NORMAL, - None, - 'float', - ), - PythonFunctionArgument( - 'd', - PythonArgumentKind.NORMAL, - None, - 'list', - ), - PythonFunctionArgument( - 'e', - PythonArgumentKind.KEYWORD_ONLY, - None, - 'tuple', - ), - PythonFunctionArgument( - 'f', - PythonArgumentKind.KEYWORD_ONLY, - None, - 'dict', - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - 'set', - ), - ], - ), - ( - argument_list( - ( - 'a: str, b: int, /, c: float, d: list, *arg' - 's: bytes, e: tuple, f: dict, **kwargs: set' - ), + ( + argument_list('a: str'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'str', + ), + ], ), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'str', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.NORMAL, - None, - 'float', - ), - PythonFunctionArgument( - 'd', - PythonArgumentKind.NORMAL, - None, - 'list', - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - 'bytes', - ), - PythonFunctionArgument( - 'e', - PythonArgumentKind.KEYWORD_ONLY, - None, - 'tuple', - ), - PythonFunctionArgument( - 'f', - PythonArgumentKind.KEYWORD_ONLY, - None, - 'dict', - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - 'set', - ), - ], - ), - ( - argument_list( - ( - 'a: str, b: int, /, *args: bytes, ' - 'c: tuple, d: dict, **kwargs: set' - ), + ( + argument_list('a: str | int'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'str | int', + ), + ], ), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'str', + ( + argument_list('a: str, b'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'str', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + ), + ( + argument_list('a: str, b: int'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'str', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + ], + ), + ( + argument_list('a, b: int'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + ], + ), + ( + argument_list('a, b, *args'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + ], + ), + ( + argument_list('a: int, b, *args'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + ], + ), + ( + argument_list('a, b: str, *args'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + 'str', + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + ], + ), + ( + argument_list('a: int, b: str, *args'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + 'str', + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + ], + ), + ( + argument_list('a: int, b: str, *args: float'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + 'str', + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + 'float', + ), + ], + ), + ( + argument_list('a: int, b, *args: float'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + 'float', + ), + ], + ), + ( + argument_list('a: int, *args: float'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + 'float', + ), + ], + ), + ( + argument_list('a: int, /, **kwargs'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list('a: int, **kwargs: str'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + 'str', + ), + ], + ), + ( + argument_list('a: int, /, b, **kwargs'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list('a: int, /, b'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + ), + ( + argument_list('a: int, /, b, *, c'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + ], + ), + ( + argument_list('a, b, *, c'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + ], + ), + ( + argument_list('a, b, *args, c'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + ], + ), + ( + argument_list('a, b, *args, c, **kwargs'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list('a, b, /, *, c, **kwargs'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list('a, b, /, c, *, d, **kwargs'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'd', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list( + ( + 'a: str, b: int, /, c: float, d: list,' + ' *, e: tuple, f: dict, **kwargs: set' + ), ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'str', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.NORMAL, + None, + 'float', + ), + PythonFunctionArgument( + 'd', + PythonArgumentKind.NORMAL, + None, + 'list', + ), + PythonFunctionArgument( + 'e', + PythonArgumentKind.KEYWORD_ONLY, + None, + 'tuple', + ), + PythonFunctionArgument( + 'f', + PythonArgumentKind.KEYWORD_ONLY, + None, + 'dict', + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + 'set', + ), + ], + ), + ( + argument_list( + ( + 'a: str, b: int, /, c: float, d: list, *arg' + 's: bytes, e: tuple, f: dict, **kwargs: set' + ), ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - 'bytes', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'str', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.NORMAL, + None, + 'float', + ), + PythonFunctionArgument( + 'd', + PythonArgumentKind.NORMAL, + None, + 'list', + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + 'bytes', + ), + PythonFunctionArgument( + 'e', + PythonArgumentKind.KEYWORD_ONLY, + None, + 'tuple', + ), + PythonFunctionArgument( + 'f', + PythonArgumentKind.KEYWORD_ONLY, + None, + 'dict', + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + 'set', + ), + ], + ), + ( + argument_list( + ( + 'a: str, b: int, /, *args: bytes, ' + 'c: tuple, d: dict, **kwargs: set' + ), ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - 'tuple', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'str', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + 'bytes', + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + 'tuple', + ), + PythonFunctionArgument( + 'd', + PythonArgumentKind.KEYWORD_ONLY, + None, + 'dict', + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + 'set', + ), + ], + ), + ( + argument_list( + "a = 1, b = 'a', /, *args, c = None, d = True, **kwargs", ), - PythonFunctionArgument( - 'd', - PythonArgumentKind.KEYWORD_ONLY, - None, - 'dict', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + '1', + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + "'a'", + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + 'None', + None, + ), + PythonFunctionArgument( + 'd', + PythonArgumentKind.KEYWORD_ONLY, + 'True', + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list( + "a, b = 'a', /, *args, c = None, d = True, **kwargs" ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - 'set', - ), - ], - ), - ( - argument_list( - 'a = 1, b = \'a\', /, *args, c = None, d = True, **kwargs', - ), [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - '1', - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - '\'a\'', - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - 'None', - None, - ), - PythonFunctionArgument( - 'd', - PythonArgumentKind.KEYWORD_ONLY, - 'True', - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list('a, b = \'a\', /, *args, c = None, d = True, **kwargs'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - '\'a\'', - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - 'None', - None - ), - PythonFunctionArgument( - 'd', - PythonArgumentKind.KEYWORD_ONLY, - 'True', - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list('a, b , /, *args, c = None, d = True, **kwargs'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - 'None', - None, - ), - PythonFunctionArgument( - 'd', - PythonArgumentKind.KEYWORD_ONLY, - 'True', - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list('a, b , /, *args, c, d = True, **kwargs'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'd', - PythonArgumentKind.KEYWORD_ONLY, - 'True', - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list('a, b , /, *args, c, d, **kwargs'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'd', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list('a, b , /, *args, c = None, d, **kwargs'), [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'args', - PythonArgumentKind.VARARG, - None, - None, - ), - PythonFunctionArgument( - 'c', - PythonArgumentKind.KEYWORD_ONLY, - 'None', - None, - ), - PythonFunctionArgument( - 'd', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, - ), - PythonFunctionArgument( - 'kwargs', - PythonArgumentKind.KWARGS, - None, - None, - ), - ], - ), - ( - argument_list('a = 1'), - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - '1', - None, - ), - ], - ), -]) + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + "'a'", + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'c', PythonArgumentKind.KEYWORD_ONLY, 'None', None + ), + PythonFunctionArgument( + 'd', + PythonArgumentKind.KEYWORD_ONLY, + 'True', + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list('a, b , /, *args, c = None, d = True, **kwargs'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + 'None', + None, + ), + PythonFunctionArgument( + 'd', + PythonArgumentKind.KEYWORD_ONLY, + 'True', + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list('a, b , /, *args, c, d = True, **kwargs'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'd', + PythonArgumentKind.KEYWORD_ONLY, + 'True', + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list('a, b , /, *args, c, d, **kwargs'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'd', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list('a, b , /, *args, c = None, d, **kwargs'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'args', + PythonArgumentKind.VARARG, + None, + None, + ), + PythonFunctionArgument( + 'c', + PythonArgumentKind.KEYWORD_ONLY, + 'None', + None, + ), + PythonFunctionArgument( + 'd', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), + PythonFunctionArgument( + 'kwargs', + PythonArgumentKind.KWARGS, + None, + None, + ), + ], + ), + ( + argument_list('a = 1'), + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + '1', + None, + ), + ], + ), + ], +) def test_PythonASTArgumentsListParser_to_argument_list( ast_arguments_list, expected, ): - assert PythonASTArgumentsListParser( - ast_arguments_list - ).to_argument_list() == expected + assert ( + PythonASTArgumentsListParser(ast_arguments_list).to_argument_list() + == expected + ) diff --git a/tests/unit/core/python/arguments/test_PythonFunctionArgument.py b/tests/unit/core/python/arguments/test_PythonFunctionArgument.py index ec6747d..5ba42b6 100644 --- a/tests/unit/core/python/arguments/test_PythonFunctionArgument.py +++ b/tests/unit/core/python/arguments/test_PythonFunctionArgument.py @@ -23,6 +23,7 @@ from src.jcloud_docsgen.exceptions import ( ) import pytest + @pytest.mark.parametrize( 'name,kind,default,annotation,expected_exception,expected_exception_msg', [ @@ -32,7 +33,7 @@ import pytest None, None, TypeError, - 'expected \'str\', got \'NoneType\'', + "expected 'str', got 'NoneType'", ), ( 1, @@ -40,7 +41,7 @@ import pytest None, None, TypeError, - 'expected \'str\', got \'int\'', + "expected 'str', got 'int'", ), ( 42, @@ -48,7 +49,7 @@ import pytest None, None, TypeError, - 'expected \'str\', got \'int\'', + "expected 'str', got 'int'", ), ( 4.2, @@ -56,7 +57,7 @@ import pytest None, None, TypeError, - 'expected \'str\', got \'float\'', + "expected 'str', got 'float'", ), ( 4.2, @@ -64,7 +65,7 @@ import pytest None, None, TypeError, - 'expected \'str\', got \'float\'', + "expected 'str', got 'float'", ), ( 'a', @@ -72,7 +73,7 @@ import pytest 1, None, TypeError, - 'expected either \'str\' or \'NoneType\', got \'int\'', + "expected either 'str' or 'NoneType', got 'int'", ), ( 'a', @@ -80,7 +81,7 @@ import pytest None, 1, TypeError, - 'expected either \'str\' or \'NoneType\', got \'int\'', + "expected either 'str' or 'NoneType', got 'int'", ), ( 'a', @@ -88,7 +89,7 @@ import pytest None, None, TypeError, - 'expected \'PythonArgumentKind\', got \'int\'', + "expected 'PythonArgumentKind', got 'int'", ), ( 'a', @@ -384,220 +385,244 @@ def test_PythonFunctionArgument_exceptions( PythonFunctionArgument(name, kind, default, annotation) assert str(exc_info.value) == expected_exception_msg -@pytest.mark.parametrize('name', [ - 'a', - '_a', - 'a1', - 'a0', - 'a_', - '_', - '_abc', - 'abc', - 'abc_', - 'match', - 'case', - 'type', - 'ä', - 'none', - 'true', - 'false', -]) -@pytest.mark.parametrize('kind', [ - PythonArgumentKind.NORMAL, - PythonArgumentKind.POSITIONAL_ONLY, - PythonArgumentKind.KEYWORD_ONLY, -]) -@pytest.mark.parametrize('default', [ - None, - 'x', - '1', - None, -]) -@pytest.mark.parametrize('annotation', [ - None, - 'a', - 'list[int]', - '_', -]) + +@pytest.mark.parametrize( + 'name', + [ + 'a', + '_a', + 'a1', + 'a0', + 'a_', + '_', + '_abc', + 'abc', + 'abc_', + 'match', + 'case', + 'type', + 'ä', + 'none', + 'true', + 'false', + ], +) +@pytest.mark.parametrize( + 'kind', + [ + PythonArgumentKind.NORMAL, + PythonArgumentKind.POSITIONAL_ONLY, + PythonArgumentKind.KEYWORD_ONLY, + ], +) +@pytest.mark.parametrize( + 'default', + [ + None, + 'x', + '1', + None, + ], +) +@pytest.mark.parametrize( + 'annotation', + [ + None, + 'a', + 'list[int]', + '_', + ], +) def test_PythonFunctionArgument(name, kind, default, annotation): PythonFunctionArgument(name, kind, default, annotation) -@pytest.mark.parametrize('name', [ - 'a', - '_a', - 'a1', - 'a0', - 'a_', - '_', - '_abc', - 'abc', - 'abc_', - 'match', - 'case', - 'type', - 'ä', - 'none', - 'true', - 'false', -]) -@pytest.mark.parametrize('kind', [ - PythonArgumentKind.VARARG, - PythonArgumentKind.KWARGS, -]) -@pytest.mark.parametrize('annotation', [ - None, - 'a', - 'list[int]', - '_', -]) + +@pytest.mark.parametrize( + 'name', + [ + 'a', + '_a', + 'a1', + 'a0', + 'a_', + '_', + '_abc', + 'abc', + 'abc_', + 'match', + 'case', + 'type', + 'ä', + 'none', + 'true', + 'false', + ], +) +@pytest.mark.parametrize( + 'kind', + [ + PythonArgumentKind.VARARG, + PythonArgumentKind.KWARGS, + ], +) +@pytest.mark.parametrize( + 'annotation', + [ + None, + 'a', + 'list[int]', + '_', + ], +) def test_PythonFunctionArgument_asterik(name, kind, annotation): PythonFunctionArgument(name, kind, None, annotation) -@pytest.mark.parametrize('argument,expected', [ - ( - PythonFunctionArgument( + +@pytest.mark.parametrize( + 'argument,expected', + [ + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + None, + ), 'a', - PythonArgumentKind.NORMAL, - None, - None, ), - 'a', - ), - ( - PythonFunctionArgument( + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + '1', + None, + ), + 'a = 1', + ), + ( + PythonFunctionArgument( + 'a', PythonArgumentKind.NORMAL, None, 'int' + ), + 'a: int', + ), + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + '1', + 'int', + ), + 'a: int = 1', + ), + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + None, + ), 'a', - PythonArgumentKind.NORMAL, - '1', - None, ), - 'a = 1', - ), - ( - PythonFunctionArgument( + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + '1', + None, + ), + 'a = 1', + ), + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + None, + 'int', + ), + 'a: int', + ), + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.POSITIONAL_ONLY, + '1', + 'int', + ), + 'a: int = 1', + ), + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.KEYWORD_ONLY, + None, + None, + ), 'a', - PythonArgumentKind.NORMAL, - None, - 'int' ), - 'a: int', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - '1', - 'int', + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.KEYWORD_ONLY, + '1', + None, + ), + 'a = 1', ), - 'a: int = 1', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - None, + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.KEYWORD_ONLY, + None, + 'int', + ), + 'a: int', ), - 'a', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - '1', - None, + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.KEYWORD_ONLY, + '1', + 'int', + ), + 'a: int = 1', ), - 'a = 1', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - None, - 'int', + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.VARARG, + None, + None, + ), + '*a', ), - 'a: int', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.POSITIONAL_ONLY, - '1', - 'int', + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.VARARG, + None, + 'int', + ), + '*a: int', ), - 'a: int = 1', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.KEYWORD_ONLY, - None, - None, + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.KWARGS, + None, + None, + ), + '**a', ), - 'a', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.KEYWORD_ONLY, - '1', - None, + ( + PythonFunctionArgument( + 'a', + PythonArgumentKind.KWARGS, + None, + 'int', + ), + '**a: int', ), - 'a = 1', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.KEYWORD_ONLY, - None, - 'int', - ), - 'a: int', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.KEYWORD_ONLY, - '1', - 'int', - ), - 'a: int = 1', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.VARARG, - None, - None, - ), - '*a', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.VARARG, - None, - 'int', - ), - '*a: int', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.KWARGS, - None, - None, - ), - '**a', - ), - ( - PythonFunctionArgument( - 'a', - PythonArgumentKind.KWARGS, - None, - 'int', - ), - '**a: int', - ), -]) + ], +) def test_PythonFunctionArgument_signature_repr(argument, expected): assert argument.signature_repr() == expected diff --git a/tests/unit/core/python/definitions/test_PythonClassDefinition.py b/tests/unit/core/python/definitions/test_PythonClassDefinition.py index 6bd3c51..b2f1291 100644 --- a/tests/unit/core/python/definitions/test_PythonClassDefinition.py +++ b/tests/unit/core/python/definitions/test_PythonClassDefinition.py @@ -25,31 +25,35 @@ from src.jcloud_docsgen.exceptions import InvalidPythonIdentifierError from tests.utils.ast_node import ast_node import pytest -@pytest.mark.parametrize('definition,expected', [ - ( - PythonClassDefinition( - 'A', - [], - None, - None, - [], - ), - 'PythonClassDefinition(\'A\', [], None, None, [])', - ), - ( - PythonClassDefinition( - 'A', - [], - None, - PythonDocstring('Hello, World!'), - [], + +@pytest.mark.parametrize( + 'definition,expected', + [ + ( + PythonClassDefinition( + 'A', + [], + None, + None, + [], + ), + "PythonClassDefinition('A', [], None, None, [])", ), ( - 'PythonClassDefinition(\'A\', [], None, ' - 'PythonDocstring(\'Hello, World!\'), [])' + PythonClassDefinition( + 'A', + [], + None, + PythonDocstring('Hello, World!'), + [], + ), + ( + "PythonClassDefinition('A', [], None, " + "PythonDocstring('Hello, World!'), [])" + ), ), - ), -]) + ], +) def test_PythonDefinition_string_representation(definition, expected): assert repr(definition) == expected @@ -364,129 +368,132 @@ def test_PythonFunctionDefinition_exceptions( assert str(exc_info.value) == expected_exception_message -@pytest.mark.parametrize('node,expected', [ - ( - ast_node( - ( - '@decorator\nclass Class(BaseClass1, BaseClass2)' - ':\n\tdef __init__(self, value: object) -> None:' - '\n\t\tself._value = value\n\n\t@property\n\tdef' - ' value(self) -> object:\n\t\treturn self._value' +@pytest.mark.parametrize( + 'node,expected', + [ + ( + ast_node( + ( + '@decorator\nclass Class(BaseClass1, BaseClass2)' + ':\n\tdef __init__(self, value: object) -> None:' + '\n\t\tself._value = value\n\n\t@property\n\tdef' + ' value(self) -> object:\n\t\treturn self._value' + ), + ), + PythonClassDefinition( + 'Class', + ['BaseClass1', 'BaseClass2'], + None, + ['decorator'], + [ + PythonFunctionDefinition( + '__init__', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + PythonFunctionArgument( + 'value', + PythonArgumentKind.NORMAL, + None, + 'object', + ), + ], + 'None', + None, + [], + ), + PythonFunctionDefinition( + 'value', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + 'object', + None, + ['property'], + ), + ], ), ), - PythonClassDefinition( - 'Class', - ['BaseClass1', 'BaseClass2'], - None, - ['decorator'], - [ - PythonFunctionDefinition( - '__init__', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - PythonFunctionArgument( - 'value', - PythonArgumentKind.NORMAL, - None, - 'object', - ), - ], - 'None', - None, - [], - ), - PythonFunctionDefinition( - 'value', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - 'object', - None, - ['property'], - ), - ], + ( + ast_node('class Class: ...'), + PythonClassDefinition( + 'Class', + [], + None, + [], + [], + ), ), - ), - ( - ast_node('class Class: ...'), - PythonClassDefinition( - 'Class', - [], - None, - [], - [], + ( + ast_node("class Class: '''docstring'''"), + PythonClassDefinition( + 'Class', + [], + PythonDocstring('docstring'), + [], + [], + ), ), - ), - ( - ast_node('class Class: \'\'\'docstring\'\'\''), - PythonClassDefinition( - 'Class', - [], - PythonDocstring('docstring'), - [], - [], + ( + ast_node('class Class:\n\tdef __init__(self): ...'), + PythonClassDefinition( + 'Class', + [], + None, + [], + [ + PythonFunctionDefinition( + '__init__', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ) + ], + None, + None, + [], + ), + ], + ), ), - ), - ( - ast_node('class Class:\n\tdef __init__(self): ...'), - PythonClassDefinition( - 'Class', - [], - None, - [], - [ - PythonFunctionDefinition( - '__init__', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ) - ], - None, - None, - [], - ), - ], + ( + ast_node("class Class:\n\t'''doc'''\n\tdef __init__(self): ..."), + PythonClassDefinition( + 'Class', + [], + PythonDocstring('doc'), + [], + [ + PythonFunctionDefinition( + '__init__', + [ + PythonFunctionArgument( + 'self', + PythonArgumentKind.NORMAL, + None, + None, + ), + ], + None, + None, + [], + ), + ], + ), ), - ), - ( - ast_node('class Class:\n\t\'\'\'doc\'\'\'\n\tdef __init__(self): ...'), - PythonClassDefinition( - 'Class', - [], - PythonDocstring('doc'), - [], - [ - PythonFunctionDefinition( - '__init__', - [ - PythonFunctionArgument( - 'self', - PythonArgumentKind.NORMAL, - None, - None, - ), - ], - None, - None, - [], - ), - ], - ), - ), -]) + ], +) def test_PythonDefinition_from_node(node, expected): assert PythonClassDefinition.from_node(node) == expected diff --git a/tests/unit/core/python/definitions/test_PythonDefinition.py b/tests/unit/core/python/definitions/test_PythonDefinition.py index 57efca3..da947a5 100644 --- a/tests/unit/core/python/definitions/test_PythonDefinition.py +++ b/tests/unit/core/python/definitions/test_PythonDefinition.py @@ -17,24 +17,28 @@ from src.jcloud_docsgen.core.python.docstrings import PythonDocstring from src.jcloud_docsgen.exceptions import InvalidPythonIdentifierError import pytest -@pytest.mark.parametrize('definition,expected', [ - ( - PythonDefinition( - 'a', - None, - [], + +@pytest.mark.parametrize( + 'definition,expected', + [ + ( + PythonDefinition( + 'a', + None, + [], + ), + "PythonDefinition('a', None, [])", ), - 'PythonDefinition(\'a\', None, [])', - ), - ( - PythonDefinition( - 'a', - PythonDocstring('Hello, World!'), - [], + ( + PythonDefinition( + 'a', + PythonDocstring('Hello, World!'), + [], + ), + "PythonDefinition('a', PythonDocstring('Hello, World!'), [])", ), - 'PythonDefinition(\'a\', PythonDocstring(\'Hello, World!\'), [])', - ), -]) + ], +) def test_PythonDefinition_string_representation(definition, expected): assert repr(definition) == expected @@ -280,164 +284,167 @@ def test_PythonDefinition_exceptions( assert str(exc_info.value) == expected_exception_message -@pytest.mark.parametrize('definition1,definition2,expected', [ - ( - PythonDefinition( - 'a', - None, - [], +@pytest.mark.parametrize( + 'definition1,definition2,expected', + [ + ( + PythonDefinition( + 'a', + None, + [], + ), + PythonDefinition( + 'a', + None, + [], + ), + True, ), - PythonDefinition( - 'a', - None, - [], + ( + PythonDefinition( + 'a', + PythonDocstring('doc'), + [], + ), + PythonDefinition( + 'a', + PythonDocstring('doc'), + [], + ), + True, ), - True, - ), - ( - PythonDefinition( - 'a', - PythonDocstring('doc'), - [], + ( + PythonDefinition( + 'a', + PythonDocstring('doc'), + ['a'], + ), + PythonDefinition( + 'a', + PythonDocstring('doc'), + ['a'], + ), + True, ), - PythonDefinition( - 'a', - PythonDocstring('doc'), - [], + ( + PythonDefinition( + 'a', + PythonDocstring('doc'), + ['a', 'b'], + ), + PythonDefinition( + 'a', + PythonDocstring('doc'), + ['a', 'b'], + ), + True, ), - True, - ), - ( - PythonDefinition( - 'a', - PythonDocstring('doc'), - ['a'], + ( + PythonDefinition( + 'a', + None, + [], + ), + PythonDefinition( + 'b', + None, + [], + ), + False, ), - PythonDefinition( - 'a', - PythonDocstring('doc'), - ['a'], + ( + PythonDefinition( + 'a', + PythonDocstring('doc'), + [], + ), + PythonDefinition( + 'a', + None, + [], + ), + False, ), - True, - ), - ( - PythonDefinition( - 'a', - PythonDocstring('doc'), - ['a', 'b'], + ( + PythonDefinition( + 'a', + PythonDocstring('doc'), + [], + ), + PythonDefinition( + 'a', + PythonDocstring('docs'), + [], + ), + False, ), - PythonDefinition( - 'a', - PythonDocstring('doc'), - ['a', 'b'], + ( + PythonDefinition( + 'a', + None, + ['a'], + ), + PythonDefinition( + 'a', + None, + ['b'], + ), + False, ), - True, - ), - ( - PythonDefinition( - 'a', - None, - [], + ( + PythonDefinition( + 'a', + None, + ['a'], + ), + PythonDefinition( + 'a', + None, + [], + ), + False, ), - PythonDefinition( - 'b', - None, - [], + ( + PythonDefinition( + 'a', + None, + ['a'], + ), + PythonDefinition( + 'a', + None, + ['a', 'b'], + ), + False, ), - False, - ), - ( - PythonDefinition( - 'a', - PythonDocstring('doc'), - [], + ( + PythonDefinition( + 'a', + None, + ['b', 'a'], + ), + PythonDefinition( + 'a', + None, + ['a', 'b'], + ), + False, ), - PythonDefinition( - 'a', - None, - [], + ( + PythonDefinition( + 'a', + PythonDocstring('doc'), + [], + ), + PythonDefinition( + 'b', + None, + ['a', 'b'], + ), + False, ), - False, - ), - ( - PythonDefinition( - 'a', - PythonDocstring('doc'), - [], - ), - PythonDefinition( - 'a', - PythonDocstring('docs'), - [], - ), - False, - ), - ( - PythonDefinition( - 'a', - None, - ['a'], - ), - PythonDefinition( - 'a', - None, - ['b'], - ), - False, - ), - ( - PythonDefinition( - 'a', - None, - ['a'], - ), - PythonDefinition( - 'a', - None, - [], - ), - False, - ), - ( - PythonDefinition( - 'a', - None, - ['a'], - ), - PythonDefinition( - 'a', - None, - ['a', 'b'], - ), - False, - ), - ( - PythonDefinition( - 'a', - None, - ['b', 'a'], - ), - PythonDefinition( - 'a', - None, - ['a', 'b'], - ), - False, - ), - ( - PythonDefinition( - 'a', - PythonDocstring('doc'), - [], - ), - PythonDefinition( - 'b', - None, - ['a', 'b'], - ), - False, - ), -]) + ], +) def test_PythonDefinition___eq__(definition1, definition2, expected): assert (definition1 == definition2) == expected assert (definition2 == definition1) == expected diff --git a/tests/unit/core/python/definitions/test_PythonFunctionDefinition.py b/tests/unit/core/python/definitions/test_PythonFunctionDefinition.py index c119ecb..9cad10b 100644 --- a/tests/unit/core/python/definitions/test_PythonFunctionDefinition.py +++ b/tests/unit/core/python/definitions/test_PythonFunctionDefinition.py @@ -22,31 +22,35 @@ from src.jcloud_docsgen.exceptions import InvalidPythonIdentifierError from tests.utils.ast_node import ast_node import pytest -@pytest.mark.parametrize('definition,expected', [ - ( - PythonFunctionDefinition( - 'a', - [], - None, - None, - [], - ), - 'PythonFunctionDefinition(\'a\', [], None, None, [])', - ), - ( - PythonFunctionDefinition( - 'a', - [], - None, - PythonDocstring('Hello, World!'), - [], + +@pytest.mark.parametrize( + 'definition,expected', + [ + ( + PythonFunctionDefinition( + 'a', + [], + None, + None, + [], + ), + "PythonFunctionDefinition('a', [], None, None, [])", ), ( - 'PythonFunctionDefinition(\'a\', [], None,' - ' PythonDocstring(\'Hello, World!\'), [])' + PythonFunctionDefinition( + 'a', + [], + None, + PythonDocstring('Hello, World!'), + [], + ), + ( + "PythonFunctionDefinition('a', [], None," + " PythonDocstring('Hello, World!'), [])" + ), ), - ), -]) + ], +) def test_PythonDefinition_string_representation(definition, expected): assert repr(definition) == expected @@ -57,295 +61,296 @@ def test_PythonDefinition_string_representation(definition, expected): 'ed_exception,expected_exception_message' ), [ - ( - '', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier', - ), - ( - '.', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: .', - ), - ( - '#', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: #', - ), - ( - '1a', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: 1a', - ), - ( - '1_', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: 1_', - ), - ( - '1,', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: 1,', - ), - ( - ',', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: ,', - ), - ( - ':', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: :', - ), - ( - '-', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: -', - ), - ( - ';', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: ;', - ), - ( - '|', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: |', - ), - ( - '<', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: <', - ), - ( - '>', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: >', - ), - ( - 'a,', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: a,', - ), - ( - ',a', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: ,a', - ), - ( - 'a:', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: a:', - ), - ( - ':a', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: :a', - ), - ( - 'a-', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: a-', - ), - ( - '-a', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: -a', - ), - ( - 'a;', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: a;', - ), - ( - ';a', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: ;a', - ), - ( - 'a|', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: a|', - ), - ( - '|a', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: |a', - ), - ( - 'a<', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: a<', - ), - ( - '', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: a>', - ), - ( - '>a', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: >a', - ), - ( - 'class', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: class', - ), - ( - 'def', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: def', - ), - ( - 'lambda', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: lambda', - ), - ( - 'None', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: None', - ), - ( - 'True', - [], - None, - None, - [], - InvalidPythonIdentifierError, - 'invalid identifier: True', - ), -]) + ( + '', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier', + ), + ( + '.', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: .', + ), + ( + '#', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: #', + ), + ( + '1a', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: 1a', + ), + ( + '1_', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: 1_', + ), + ( + '1,', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: 1,', + ), + ( + ',', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: ,', + ), + ( + ':', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: :', + ), + ( + '-', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: -', + ), + ( + ';', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: ;', + ), + ( + '|', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: |', + ), + ( + '<', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: <', + ), + ( + '>', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: >', + ), + ( + 'a,', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: a,', + ), + ( + ',a', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: ,a', + ), + ( + 'a:', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: a:', + ), + ( + ':a', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: :a', + ), + ( + 'a-', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: a-', + ), + ( + '-a', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: -a', + ), + ( + 'a;', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: a;', + ), + ( + ';a', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: ;a', + ), + ( + 'a|', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: a|', + ), + ( + '|a', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: |a', + ), + ( + 'a<', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: a<', + ), + ( + '', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: a>', + ), + ( + '>a', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: >a', + ), + ( + 'class', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: class', + ), + ( + 'def', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: def', + ), + ( + 'lambda', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: lambda', + ), + ( + 'None', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: None', + ), + ( + 'True', + [], + None, + None, + [], + InvalidPythonIdentifierError, + 'invalid identifier: True', + ), + ], +) def test_PythonFunctionDefinition_exceptions( name, args, @@ -360,100 +365,106 @@ def test_PythonFunctionDefinition_exceptions( assert str(exc_info.value) == expected_exception_message -@pytest.mark.parametrize('node,expected', [ - ( - ast_node('def add(a: int, b: int) -> int: return a + b'), - PythonFunctionDefinition( - 'add', [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - ], - 'int', - None, - [], - ), - ), - ( - ast_node('@decorator\ndef add(a: int, b: int) -> int: return a + b'), - PythonFunctionDefinition( - 'add', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - ], - 'int', - None, - ['decorator'], - ), - ), - ( - ast_node( - ( - '@decorator1\n@decorator2\ndef add(a' - ': int, b: int) -> int: return a + b' +@pytest.mark.parametrize( + 'node,expected', + [ + ( + ast_node('def add(a: int, b: int) -> int: return a + b'), + PythonFunctionDefinition( + 'add', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + ], + 'int', + None, + [], ), ), - PythonFunctionDefinition( - 'add', - [ - PythonFunctionArgument( - 'a', - PythonArgumentKind.NORMAL, - None, - 'int', + ( + ast_node( + '@decorator\ndef add(a: int, b: int) -> int: return a + b' + ), + PythonFunctionDefinition( + 'add', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + ], + 'int', + None, + ['decorator'], + ), + ), + ( + ast_node( + ( + '@decorator1\n@decorator2\ndef add(a' + ': int, b: int) -> int: return a + b' ), - PythonFunctionArgument( - 'b', - PythonArgumentKind.NORMAL, - None, - 'int', - ), - ], - 'int', - None, - ['decorator1', 'decorator2'], + ), + PythonFunctionDefinition( + 'add', + [ + PythonFunctionArgument( + 'a', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + PythonFunctionArgument( + 'b', + PythonArgumentKind.NORMAL, + None, + 'int', + ), + ], + 'int', + None, + ['decorator1', 'decorator2'], + ), ), - ), - ( - ast_node('def func(): ...'), - PythonFunctionDefinition( - 'func', - [], - None, - None, - [], + ( + ast_node('def func(): ...'), + PythonFunctionDefinition( + 'func', + [], + None, + None, + [], + ), ), - ), - ( - ast_node('@decorator\ndef func(): ...'), - PythonFunctionDefinition( - 'func', - [], - None, - None, - ['decorator'], + ( + ast_node('@decorator\ndef func(): ...'), + PythonFunctionDefinition( + 'func', + [], + None, + None, + ['decorator'], + ), ), - ), -]) + ], +) def test_PythonDefinition_from_node(node, expected): assert PythonFunctionDefinition.from_node(node) == expected diff --git a/tests/unit/core/python/namespaces/test_PythonModuleNamespace.py b/tests/unit/core/python/namespaces/test_PythonModuleNamespace.py index 9525f28..612e00c 100644 --- a/tests/unit/core/python/namespaces/test_PythonModuleNamespace.py +++ b/tests/unit/core/python/namespaces/test_PythonModuleNamespace.py @@ -15,33 +15,49 @@ from src.jcloud_docsgen.core.python.namespaces import PythonModuleNamespace import pytest + class StrSubclass(str): ... -@pytest.mark.parametrize('namespace,expected_name', [ - (PythonModuleNamespace('a'), 'a'), - (PythonModuleNamespace('1'), '1'), - (PythonModuleNamespace(StrSubclass('a')), StrSubclass('a')), -]) + +@pytest.mark.parametrize( + 'namespace,expected_name', + [ + (PythonModuleNamespace('a'), 'a'), + (PythonModuleNamespace('1'), '1'), + (PythonModuleNamespace(StrSubclass('a')), StrSubclass('a')), + ], +) def test_PythonModuleNamespace_name_attribute(namespace, expected_name): assert namespace.name == expected_name -@pytest.mark.parametrize('namespace1,namespace2,expected', [ - (PythonModuleNamespace('a'), PythonModuleNamespace('a'), True), - (PythonModuleNamespace('b'), PythonModuleNamespace('b'), True), - (PythonModuleNamespace('1'), PythonModuleNamespace('1'), True), - (PythonModuleNamespace('42'), PythonModuleNamespace('42'), True), - (PythonModuleNamespace('a'), PythonModuleNamespace('b'), False), - (PythonModuleNamespace('0'), PythonModuleNamespace('-0'), False), - (PythonModuleNamespace('1'), PythonModuleNamespace('a'), False), -]) + +@pytest.mark.parametrize( + 'namespace1,namespace2,expected', + [ + (PythonModuleNamespace('a'), PythonModuleNamespace('a'), True), + (PythonModuleNamespace('b'), PythonModuleNamespace('b'), True), + (PythonModuleNamespace('1'), PythonModuleNamespace('1'), True), + (PythonModuleNamespace('42'), PythonModuleNamespace('42'), True), + (PythonModuleNamespace('a'), PythonModuleNamespace('b'), False), + (PythonModuleNamespace('0'), PythonModuleNamespace('-0'), False), + (PythonModuleNamespace('1'), PythonModuleNamespace('a'), False), + ], +) def test_PythonModuleNamespace___eq__(namespace1, namespace2, expected): assert (namespace1 == namespace2) == expected assert (namespace2 == namespace1) == expected -@pytest.mark.parametrize('namespace,expected', [ - (PythonModuleNamespace('a'), 'PythonModuleNamespace(\'a\')'), - (PythonModuleNamespace('1'), 'PythonModuleNamespace(\'1\')'), - (PythonModuleNamespace(StrSubclass('a')), 'PythonModuleNamespace(\'a\')'), -]) + +@pytest.mark.parametrize( + 'namespace,expected', + [ + (PythonModuleNamespace('a'), "PythonModuleNamespace('a')"), + (PythonModuleNamespace('1'), "PythonModuleNamespace('1')"), + ( + PythonModuleNamespace(StrSubclass('a')), + "PythonModuleNamespace('a')", + ), + ], +) def test_PythonModuleNamespace_string_representation(namespace, expected): assert repr(namespace) == expected diff --git a/tests/unit/core/python/namespaces/test_PythonNamespace.py b/tests/unit/core/python/namespaces/test_PythonNamespace.py index 440221b..3f845bf 100644 --- a/tests/unit/core/python/namespaces/test_PythonNamespace.py +++ b/tests/unit/core/python/namespaces/test_PythonNamespace.py @@ -15,20 +15,29 @@ from src.jcloud_docsgen.core.python.namespaces import PythonNamespace import pytest + class StrSubclass(str): ... -@pytest.mark.parametrize('namespace,expected_name', [ - (PythonNamespace('a'), 'a'), - (PythonNamespace('1'), '1'), - (PythonNamespace(StrSubclass('a')), StrSubclass('a')), -]) + +@pytest.mark.parametrize( + 'namespace,expected_name', + [ + (PythonNamespace('a'), 'a'), + (PythonNamespace('1'), '1'), + (PythonNamespace(StrSubclass('a')), StrSubclass('a')), + ], +) def test_PythonNamespace_name_attribute(namespace, expected_name): assert namespace.name == expected_name -@pytest.mark.parametrize('namespace,expected', [ - (PythonNamespace('a'), 'PythonNamespace(\'a\')'), - (PythonNamespace('1'), 'PythonNamespace(\'1\')'), - (PythonNamespace(StrSubclass('a')), 'PythonNamespace(\'a\')'), -]) + +@pytest.mark.parametrize( + 'namespace,expected', + [ + (PythonNamespace('a'), "PythonNamespace('a')"), + (PythonNamespace('1'), "PythonNamespace('1')"), + (PythonNamespace(StrSubclass('a')), "PythonNamespace('a')"), + ], +) def test_PythonNamespace_string_representation(namespace, expected): assert repr(namespace) == expected diff --git a/tests/unit/core/python/namespaces/test_PythonPackageNamespace.py b/tests/unit/core/python/namespaces/test_PythonPackageNamespace.py index e8a5af9..05d830e 100644 --- a/tests/unit/core/python/namespaces/test_PythonPackageNamespace.py +++ b/tests/unit/core/python/namespaces/test_PythonPackageNamespace.py @@ -22,38 +22,47 @@ from src.jcloud_docsgen.exceptions import ( InvalidNamespaceError, ) + class StrSubclass(str): ... -@pytest.mark.parametrize('namespace,expected_name', [ - ( - PythonPackageNamespace( + +@pytest.mark.parametrize( + 'namespace,expected_name', + [ + ( + PythonPackageNamespace( + 'a', + [], + ), 'a', - [], ), - 'a', - ), - ( - PythonPackageNamespace( + ( + PythonPackageNamespace( + '1', + [], + ), '1', - [], ), - '1', - ), - ( - PythonPackageNamespace( + ( + PythonPackageNamespace( + StrSubclass('a'), + [], + ), StrSubclass('a'), - [], ), - StrSubclass('a'), - ), -]) + ], +) def test_PythonPackageNamespace_name_attribute(namespace, expected_name): assert namespace.name == expected_name + namespace_b = PythonModuleNamespace('b') -namespace_a = PythonPackageNamespace('a', [ - namespace_b, -]) +namespace_a = PythonPackageNamespace( + 'a', + [ + namespace_b, + ], +) namespace_c = PythonModuleNamespace('c') namespace_k = PythonModuleNamespace('k') namespace_j = PythonPackageNamespace('j', [namespace_k]) @@ -64,47 +73,51 @@ namespace_f = PythonPackageNamespace('f', [namespace_g]) namespace_e = PythonPackageNamespace('e', [namespace_f]) namespace_d = PythonPackageNamespace('d', [namespace_e]) -@pytest.mark.parametrize('namespace,sub_namespaces,expected', [ - ( - PythonPackageNamespace( - 'name', - [namespace_a, namespace_c], + +@pytest.mark.parametrize( + 'namespace,sub_namespaces,expected', + [ + ( + PythonPackageNamespace( + 'name', + [namespace_a, namespace_c], + ), + ['c'], + namespace_c, ), - ['c'], - namespace_c, - ), - ( - PythonPackageNamespace( - 'name', - [namespace_a, namespace_c], + ( + PythonPackageNamespace( + 'name', + [namespace_a, namespace_c], + ), + ['a'], + namespace_a, ), - ['a'], - namespace_a, - ), - ( - PythonPackageNamespace( - 'name', - [namespace_a, namespace_c], + ( + PythonPackageNamespace( + 'name', + [namespace_a, namespace_c], + ), + ['a', 'b'], + namespace_b, ), - ['a', 'b'], - namespace_b, - ), - ( - namespace_d, - ['e', 'f', 'g', 'h', 'i'], - namespace_i, - ), - ( - namespace_d, - ['e', 'f', 'g', 'h', 'i', 'j'], - namespace_j, - ), - ( - namespace_d, - ['e', 'f', 'g', 'h', 'i', 'j', 'k'], - namespace_k, - ), -]) + ( + namespace_d, + ['e', 'f', 'g', 'h', 'i'], + namespace_i, + ), + ( + namespace_d, + ['e', 'f', 'g', 'h', 'i', 'j'], + namespace_j, + ), + ( + namespace_d, + ['e', 'f', 'g', 'h', 'i', 'j', 'k'], + namespace_k, + ), + ], +) def test_PythonPackageNamespace_namespace( namespace: PythonPackageNamespace, sub_namespaces, @@ -112,6 +125,7 @@ def test_PythonPackageNamespace_namespace( ): assert namespace.namespace(sub_namespaces) == expected + @pytest.mark.parametrize( 'namespace,sub_namespaces,expected_exception,expected_exception_msg', [ @@ -157,129 +171,145 @@ def test_PythonPackageNamespace_namespace_exceptions( namespace.namespace(sub_namespaces) assert str(exc_info.value) == expected_exception_msg -@pytest.mark.parametrize('namespace,expected', [ - ( - PythonPackageNamespace( - 'a', - [PythonModuleNamespace('b')], + +@pytest.mark.parametrize( + 'namespace,expected', + [ + ( + PythonPackageNamespace( + 'a', + [PythonModuleNamespace('b')], + ), + {'b': 'b'}, ), - {'b': 'b'}, - ), - ( - PythonPackageNamespace( - 'a', - [ - PythonModuleNamespace('b'), - PythonPackageNamespace( - 'c', - [PythonModuleNamespace('d')], - ), - ], + ( + PythonPackageNamespace( + 'a', + [ + PythonModuleNamespace('b'), + PythonPackageNamespace( + 'c', + [PythonModuleNamespace('d')], + ), + ], + ), + { + 'b': 'b', + 'c': {'d': 'd'}, + }, ), - { - 'b': 'b', - 'c': {'d': 'd'}, - }, - ), - ( - PythonPackageNamespace('a', []), - {}, - ), -]) + ( + PythonPackageNamespace('a', []), + {}, + ), + ], +) def test_PythonPackageNamespace_sub_namespace_names(namespace, expected): assert namespace.sub_namespace_names() == expected -@pytest.mark.parametrize('namespace1,namespace2,expected', [ - ( - PythonPackageNamespace( - 'a', - [PythonModuleNamespace('b')], + +@pytest.mark.parametrize( + 'namespace1,namespace2,expected', + [ + ( + PythonPackageNamespace( + 'a', + [PythonModuleNamespace('b')], + ), + PythonPackageNamespace( + 'a', + [PythonModuleNamespace('b')], + ), + True, ), - PythonPackageNamespace( - 'a', - [PythonModuleNamespace('b')], + ( + PythonPackageNamespace( + 'a', + [ + PythonModuleNamespace('b'), + PythonPackageNamespace( + 'c', + [PythonModuleNamespace('d')], + ), + ], + ), + PythonPackageNamespace( + 'a', + [ + PythonModuleNamespace('b'), + PythonPackageNamespace( + 'c', + [PythonModuleNamespace('d')], + ), + ], + ), + True, ), - True, - ), - ( - PythonPackageNamespace( - 'a', - [ - PythonModuleNamespace('b'), - PythonPackageNamespace( - 'c', - [PythonModuleNamespace('d')], - ), - ], + ( + PythonPackageNamespace('a', []), + PythonPackageNamespace('a', []), + True, ), - PythonPackageNamespace( - 'a', - [ - PythonModuleNamespace('b'), - PythonPackageNamespace( - 'c', - [PythonModuleNamespace('d')], - ), - ], + ( + PythonPackageNamespace('a', []), + PythonPackageNamespace('b', []), + False, ), - True, - ), - ( - PythonPackageNamespace('a', []), - PythonPackageNamespace('a', []), - True, - ), - ( - PythonPackageNamespace('a', []), - PythonPackageNamespace('b', []), - False, - ), -]) + ], +) def test_PythonPackageNamespace___eq__(namespace1, namespace2, expected): assert (namespace1 == namespace2) == expected assert (namespace2 == namespace1) == expected -@pytest.mark.parametrize('namespace,expected', [ - ( - PythonPackageNamespace('a', []), - 'PythonPackageNamespace(\'a\', [])', - ), - ( - PythonPackageNamespace('1', []), - 'PythonPackageNamespace(\'1\', [])', - ), - ( - PythonPackageNamespace(StrSubclass('a'), []), - 'PythonPackageNamespace(\'a\', [])', - ), - ( - namespace_a, - 'PythonPackageNamespace(\'a\', [PythonModuleNamespace(\'b\')])', - ), - ( - namespace_d, + +@pytest.mark.parametrize( + 'namespace,expected', + [ ( - 'PythonPackageNamespace(\'d\', [PythonPackageNamespac' - 'e(\'e\', [PythonPackageNamespace(\'f\', [PythonPacka' - 'geNamespace(\'g\', [PythonPackageNamespace(\'h\', [P' - 'ythonPackageNamespace(\'i\', [PythonPackageNamespace' - '(\'j\', [PythonModuleNamespace(\'k\')])])])])])])])' + PythonPackageNamespace('a', []), + "PythonPackageNamespace('a', [])", ), - ), -]) + ( + PythonPackageNamespace('1', []), + "PythonPackageNamespace('1', [])", + ), + ( + PythonPackageNamespace(StrSubclass('a'), []), + "PythonPackageNamespace('a', [])", + ), + ( + namespace_a, + "PythonPackageNamespace('a', [PythonModuleNamespace('b')])", + ), + ( + namespace_d, + ( + "PythonPackageNamespace('d', [PythonPackageNamespac" + "e('e', [PythonPackageNamespace('f', [PythonPacka" + "geNamespace('g', [PythonPackageNamespace('h', [P" + "ythonPackageNamespace('i', [PythonPackageNamespace" + "('j', [PythonModuleNamespace('k')])])])])])])])" + ), + ), + ], +) def test_PythonPackageNamespace_string_representation(namespace, expected): assert repr(namespace) == expected -@pytest.mark.parametrize('namespace,new_namespace,expected', [ - ( - PythonPackageNamespace('a', []), - PythonModuleNamespace('b'), - PythonPackageNamespace( - 'a', - [PythonModuleNamespace('b')], + +@pytest.mark.parametrize( + 'namespace,new_namespace,expected', + [ + ( + PythonPackageNamespace('a', []), + PythonModuleNamespace('b'), + PythonPackageNamespace( + 'a', + [PythonModuleNamespace('b')], + ), ), - ), -]) + ], +) def test_PythonPackageNamespace___getitem__( namespace, new_namespace, diff --git a/tests/unit/utils/test_assert_that_is_instance.py b/tests/unit/utils/test_assert_that_is_instance.py index 54d69b2..f51009f 100644 --- a/tests/unit/utils/test_assert_that_is_instance.py +++ b/tests/unit/utils/test_assert_that_is_instance.py @@ -16,47 +16,58 @@ from src.jcloud_docsgen.utils import assert_that_is_instance import pytest import types + class TestType: ... + + TestType.__name__ = 'NOT TestType' -@pytest.mark.parametrize('obj,class_or_tuple', [ - (1, int), - (1, (int,)), - (1, str | int), - (1, int | str | list), - (TestType(), TestType), - (None, types.NoneType), -]) + +@pytest.mark.parametrize( + 'obj,class_or_tuple', + [ + (1, int), + (1, (int,)), + (1, str | int), + (1, int | str | list), + (TestType(), TestType), + (None, types.NoneType), + ], +) def test_assert_that_is_instance(obj, class_or_tuple): assert_that_is_instance(obj, class_or_tuple) -@pytest.mark.parametrize('obj,class_or_tuple,expected_exception_msg', [ - ( - 1, - str, - 'expected \'str\', got \'int\'', - ), - ( - 1, - (str,), - 'expected \'str\', got \'int\'', - ), - ( - 1, - str | float, - 'expected either \'str\' or \'float\', got \'int\'', - ), - ( - 1, - str | float | list, - 'expected either \'str\', \'float\' or \'list\', got \'int\'', - ), - ( - 1, - TestType, - 'expected \'NOT TestType\', got \'int\'', - ), -]) + +@pytest.mark.parametrize( + 'obj,class_or_tuple,expected_exception_msg', + [ + ( + 1, + str, + "expected 'str', got 'int'", + ), + ( + 1, + (str,), + "expected 'str', got 'int'", + ), + ( + 1, + str | float, + "expected either 'str' or 'float', got 'int'", + ), + ( + 1, + str | float | list, + "expected either 'str', 'float' or 'list', got 'int'", + ), + ( + 1, + TestType, + "expected 'NOT TestType', got 'int'", + ), + ], +) def test_assert_that_is_instance_exceptions( obj, class_or_tuple, diff --git a/tests/unit/utils/test_get_relative_path_segments.py b/tests/unit/utils/test_get_relative_path_segments.py index 66ba580..a418afd 100644 --- a/tests/unit/utils/test_get_relative_path_segments.py +++ b/tests/unit/utils/test_get_relative_path_segments.py @@ -16,61 +16,62 @@ from src.jcloud_docsgen.utils import get_relative_path_segments import pytest import pathlib -@pytest.mark.parametrize('path,root,expected', [ - (pathlib.Path('/'), pathlib.Path('/'), []), - (pathlib.Path('/a'), pathlib.Path('/'), ['a']), - (pathlib.Path('/a/'), pathlib.Path('/'), ['a']), - (pathlib.Path('/a'), pathlib.Path('/a'), []), - (pathlib.Path('/a/'), pathlib.Path('/a'), []), - (pathlib.Path('/a'), pathlib.Path('/a/'), []), - (pathlib.Path('/a/'), pathlib.Path('/a/'), []), - (pathlib.Path('/a/b'), pathlib.Path('/'), ['a', 'b']), - (pathlib.Path('/a/b/'), pathlib.Path('/'), ['a', 'b']), - (pathlib.Path('/a/b'), pathlib.Path('/a'), ['b']), - (pathlib.Path('/a/b/'), pathlib.Path('/a'), ['b']), - (pathlib.Path('/a/b'), pathlib.Path('/a/'), ['b']), - (pathlib.Path('/a/b/'), pathlib.Path('/a/'), ['b']), - (pathlib.Path('/a/b'), pathlib.Path('/a/b'), []), - (pathlib.Path('/a/b/'), pathlib.Path('/a/b'), []), - (pathlib.Path('/a/b'), pathlib.Path('/a/b/'), []), - (pathlib.Path('/a/b/'), pathlib.Path('/a/b/'), []), - (pathlib.Path('./'), pathlib.Path('./'), []), - (pathlib.Path('./a'), pathlib.Path('./'), ['a']), - (pathlib.Path('./a/'), pathlib.Path('./'), ['a']), - (pathlib.Path('./a'), pathlib.Path('./a'), []), - (pathlib.Path('./a/'), pathlib.Path('./a'), []), - (pathlib.Path('./a'), pathlib.Path('./a/'), []), - (pathlib.Path('./a/'), pathlib.Path('./a/'), []), - (pathlib.Path('./a/b'), pathlib.Path('./'), ['a', 'b']), - (pathlib.Path('./a/b/'), pathlib.Path('./'), ['a', 'b']), - (pathlib.Path('./a/b'), pathlib.Path('./a'), ['b']), - (pathlib.Path('./a/b/'), pathlib.Path('./a'), ['b']), - (pathlib.Path('./a/b'), pathlib.Path('./a/'), ['b']), - (pathlib.Path('./a/b/'), pathlib.Path('./a/'), ['b']), - (pathlib.Path('./a/b'), pathlib.Path('./a/b'), []), - (pathlib.Path('./a/b/'), pathlib.Path('./a/b'), []), - (pathlib.Path('./a/b'), pathlib.Path('./a/b/'), []), - (pathlib.Path('./a/b/'), pathlib.Path('./a/b/'), []), - - (pathlib.Path(''), pathlib.Path(''), []), - (pathlib.Path('a'), pathlib.Path(''), ['a']), - (pathlib.Path('a/'), pathlib.Path(''), ['a']), - (pathlib.Path('a'), pathlib.Path('a'), []), - (pathlib.Path('a/'), pathlib.Path('a'), []), - (pathlib.Path('a'), pathlib.Path('a/'), []), - (pathlib.Path('a/'), pathlib.Path('a/'), []), - (pathlib.Path('a/b'), pathlib.Path(''), ['a', 'b']), - (pathlib.Path('a/b/'), pathlib.Path(''), ['a', 'b']), - (pathlib.Path('a/b'), pathlib.Path('a'), ['b']), - (pathlib.Path('a/b/'), pathlib.Path('a'), ['b']), - (pathlib.Path('a/b'), pathlib.Path('a/'), ['b']), - (pathlib.Path('a/b/'), pathlib.Path('a/'), ['b']), - (pathlib.Path('a/b'), pathlib.Path('a/b'), []), - (pathlib.Path('a/b/'), pathlib.Path('a/b'), []), - (pathlib.Path('a/b'), pathlib.Path('a/b/'), []), - (pathlib.Path('a/b/'), pathlib.Path('a/b/'), []), - -]) +@pytest.mark.parametrize( + 'path,root,expected', + [ + (pathlib.Path('/'), pathlib.Path('/'), []), + (pathlib.Path('/a'), pathlib.Path('/'), ['a']), + (pathlib.Path('/a/'), pathlib.Path('/'), ['a']), + (pathlib.Path('/a'), pathlib.Path('/a'), []), + (pathlib.Path('/a/'), pathlib.Path('/a'), []), + (pathlib.Path('/a'), pathlib.Path('/a/'), []), + (pathlib.Path('/a/'), pathlib.Path('/a/'), []), + (pathlib.Path('/a/b'), pathlib.Path('/'), ['a', 'b']), + (pathlib.Path('/a/b/'), pathlib.Path('/'), ['a', 'b']), + (pathlib.Path('/a/b'), pathlib.Path('/a'), ['b']), + (pathlib.Path('/a/b/'), pathlib.Path('/a'), ['b']), + (pathlib.Path('/a/b'), pathlib.Path('/a/'), ['b']), + (pathlib.Path('/a/b/'), pathlib.Path('/a/'), ['b']), + (pathlib.Path('/a/b'), pathlib.Path('/a/b'), []), + (pathlib.Path('/a/b/'), pathlib.Path('/a/b'), []), + (pathlib.Path('/a/b'), pathlib.Path('/a/b/'), []), + (pathlib.Path('/a/b/'), pathlib.Path('/a/b/'), []), + (pathlib.Path('./'), pathlib.Path('./'), []), + (pathlib.Path('./a'), pathlib.Path('./'), ['a']), + (pathlib.Path('./a/'), pathlib.Path('./'), ['a']), + (pathlib.Path('./a'), pathlib.Path('./a'), []), + (pathlib.Path('./a/'), pathlib.Path('./a'), []), + (pathlib.Path('./a'), pathlib.Path('./a/'), []), + (pathlib.Path('./a/'), pathlib.Path('./a/'), []), + (pathlib.Path('./a/b'), pathlib.Path('./'), ['a', 'b']), + (pathlib.Path('./a/b/'), pathlib.Path('./'), ['a', 'b']), + (pathlib.Path('./a/b'), pathlib.Path('./a'), ['b']), + (pathlib.Path('./a/b/'), pathlib.Path('./a'), ['b']), + (pathlib.Path('./a/b'), pathlib.Path('./a/'), ['b']), + (pathlib.Path('./a/b/'), pathlib.Path('./a/'), ['b']), + (pathlib.Path('./a/b'), pathlib.Path('./a/b'), []), + (pathlib.Path('./a/b/'), pathlib.Path('./a/b'), []), + (pathlib.Path('./a/b'), pathlib.Path('./a/b/'), []), + (pathlib.Path('./a/b/'), pathlib.Path('./a/b/'), []), + (pathlib.Path(''), pathlib.Path(''), []), + (pathlib.Path('a'), pathlib.Path(''), ['a']), + (pathlib.Path('a/'), pathlib.Path(''), ['a']), + (pathlib.Path('a'), pathlib.Path('a'), []), + (pathlib.Path('a/'), pathlib.Path('a'), []), + (pathlib.Path('a'), pathlib.Path('a/'), []), + (pathlib.Path('a/'), pathlib.Path('a/'), []), + (pathlib.Path('a/b'), pathlib.Path(''), ['a', 'b']), + (pathlib.Path('a/b/'), pathlib.Path(''), ['a', 'b']), + (pathlib.Path('a/b'), pathlib.Path('a'), ['b']), + (pathlib.Path('a/b/'), pathlib.Path('a'), ['b']), + (pathlib.Path('a/b'), pathlib.Path('a/'), ['b']), + (pathlib.Path('a/b/'), pathlib.Path('a/'), ['b']), + (pathlib.Path('a/b'), pathlib.Path('a/b'), []), + (pathlib.Path('a/b/'), pathlib.Path('a/b'), []), + (pathlib.Path('a/b'), pathlib.Path('a/b/'), []), + (pathlib.Path('a/b/'), pathlib.Path('a/b/'), []), + ], +) def test_get_relative_path_segments(path, root, expected): assert get_relative_path_segments(path, root) == expected diff --git a/tests/unit/utils/test_human_readable_list.py b/tests/unit/utils/test_human_readable_list.py index e2c921b..55d1542 100644 --- a/tests/unit/utils/test_human_readable_list.py +++ b/tests/unit/utils/test_human_readable_list.py @@ -15,45 +15,49 @@ from src.jcloud_docsgen.utils import human_readable_list import pytest -@pytest.mark.parametrize('ls,final_separator,quotation_mark,expected', [ - ([], '', '', ''), - ([], 'and', '', ''), - ([], 'and', '\'', ''), - ([1], '', '', '1'), - ([-1], '', '', '-1'), - ([0], '', '', '0'), - ([0.0], '', '', '0.0'), - ([-0.0], '', '', '-0.0'), - ([4.2], '', '', '4.2'), - ([-4.2], '', '', '-4.2'), - (['a'], '', '', 'a'), - ([1], 'and', '', '1'), - (['a'], 'and', '', 'a'), - ([1], 'and', '\'', '\'1\''), - (['a'], 'and', '\'', '\'a\''), - ([1, 2], 'and', '', '1 and 2'), - ([1, 2], 'and', '\'', '\'1\' and \'2\''), - ([1, 'a'], 'and', '', '1 and a'), - ([1, 'a'], 'and', '\'', '\'1\' and \'a\''), - ([1, 'a'], 'and', '', '1 and a'), - ([1, 'a'], 'and', '\'', '\'1\' and \'a\''), - ([1, 'a'], 'and', '\'', '\'1\' and \'a\''), - ([1, 'a'], '', '', '1 a'), - ([1, 'a'], '', '\'', '\'1\' \'a\''), - ([1, 'a'], '', '', '1 a'), - ([1, 'a'], '', '\'', '\'1\' \'a\''), - ([1, 'a'], '', '\'', '\'1\' \'a\''), - ([1, 2, 3], 'and', '', '1, 2 and 3'), - ([1, 2, 3], '', '', '1, 2 3'), - ([1, 2, 3], 'and', '\'', '\'1\', \'2\' and \'3\''), - ([1, 2, 3], '', '\'', '\'1\', \'2\' \'3\''), - ([1, 2, 3, 42, 'a', 23], 'and', '', '1, 2, 3, 42, a and 23'), - ( - [1, 2, 3, 42, 'a', 23], - 'and', - '\'', - '\'1\', \'2\', \'3\', \'42\', \'a\' and \'23\'', - ), -]) + +@pytest.mark.parametrize( + 'ls,final_separator,quotation_mark,expected', + [ + ([], '', '', ''), + ([], 'and', '', ''), + ([], 'and', "'", ''), + ([1], '', '', '1'), + ([-1], '', '', '-1'), + ([0], '', '', '0'), + ([0.0], '', '', '0.0'), + ([-0.0], '', '', '-0.0'), + ([4.2], '', '', '4.2'), + ([-4.2], '', '', '-4.2'), + (['a'], '', '', 'a'), + ([1], 'and', '', '1'), + (['a'], 'and', '', 'a'), + ([1], 'and', "'", "'1'"), + (['a'], 'and', "'", "'a'"), + ([1, 2], 'and', '', '1 and 2'), + ([1, 2], 'and', "'", "'1' and '2'"), + ([1, 'a'], 'and', '', '1 and a'), + ([1, 'a'], 'and', "'", "'1' and 'a'"), + ([1, 'a'], 'and', '', '1 and a'), + ([1, 'a'], 'and', "'", "'1' and 'a'"), + ([1, 'a'], 'and', "'", "'1' and 'a'"), + ([1, 'a'], '', '', '1 a'), + ([1, 'a'], '', "'", "'1' 'a'"), + ([1, 'a'], '', '', '1 a'), + ([1, 'a'], '', "'", "'1' 'a'"), + ([1, 'a'], '', "'", "'1' 'a'"), + ([1, 2, 3], 'and', '', '1, 2 and 3'), + ([1, 2, 3], '', '', '1, 2 3'), + ([1, 2, 3], 'and', "'", "'1', '2' and '3'"), + ([1, 2, 3], '', "'", "'1', '2' '3'"), + ([1, 2, 3, 42, 'a', 23], 'and', '', '1, 2, 3, 42, a and 23'), + ( + [1, 2, 3, 42, 'a', 23], + 'and', + "'", + "'1', '2', '3', '42', 'a' and '23'", + ), + ], +) def test_human_readable_list(ls, final_separator, quotation_mark, expected): assert human_readable_list(ls, final_separator, quotation_mark) == expected diff --git a/tests/unit/utils/test_non_empty_str.py b/tests/unit/utils/test_non_empty_str.py index 0b57d31..3f366ec 100644 --- a/tests/unit/utils/test_non_empty_str.py +++ b/tests/unit/utils/test_non_empty_str.py @@ -15,16 +15,20 @@ from src.jcloud_docsgen.utils import non_empty_str import pytest -@pytest.mark.parametrize('value,expected', [ - (None, None), - ('', None), - (' ', None), - (' ', None), - (' ', None), - (' a ', ' a '), - (' a', ' a'), - ('a ', 'a '), - ('a', 'a'), -]) + +@pytest.mark.parametrize( + 'value,expected', + [ + (None, None), + ('', None), + (' ', None), + (' ', None), + (' ', None), + (' a ', ' a '), + (' a', ' a'), + ('a ', 'a '), + ('a', 'a'), + ], +) def test_non_empty_str(value, expected): assert non_empty_str(value) == expected diff --git a/tests/utils/ast_node.py b/tests/utils/ast_node.py index 9beb441..1b164a0 100644 --- a/tests/utils/ast_node.py +++ b/tests/utils/ast_node.py @@ -15,12 +15,11 @@ from typing import Union import ast -__all__ = [ - 'ast_node' -] +__all__ = ['ast_node'] + def ast_node(statement: str) -> Union[ast.stmt, None]: - ''' + """ Returns an AST node from the statement. :param statement: The statement. @@ -28,7 +27,7 @@ def ast_node(statement: str) -> Union[ast.stmt, None]: :return: The node. :rtype: Union[ast.stmt, None] - ''' + """ body = ast.parse(statement).body if not body: