diff --git a/.flake8 b/.flake8 deleted file mode 100644 index ba265fe89..000000000 --- a/.flake8 +++ /dev/null @@ -1,3 +0,0 @@ -[flake8] -max-line-length = 120 -extend-ignore = E501, E203, B028 \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4312eb7b9..a755133cc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,30 +1,11 @@ repos: - - repo: https://github.com/psf/black - rev: 24.2.0 - hooks: - - id: black - - - repo: https://github.com/PyCQA/flake8 - rev: 7.0.0 - hooks: - - id: flake8 - additional_dependencies: - - flake8-bugbear - - flake8-comprehensions - - flake8-simplify - - pep8-naming - - - repo: https://github.com/pycqa/isort - rev: 5.13.2 - hooks: - - id: isort - - repo: https://github.com/asottile/pyupgrade - rev: v3.15.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.6 hooks: - - id: pyupgrade - args: - - --py38-plus + - id: ruff + args: [--fix] + - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.8.0 diff --git a/docs/conf.py b/docs/conf.py index c9826cfd5..f9355ad77 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -55,7 +55,9 @@ needs_debug_measurement = True add_module_names = False # Used to shorten function name output -autodoc_docstring_signature = True # Used to read spec. func-defs from docstring (e.g. get rid of self) +autodoc_docstring_signature = ( + True # Used to read spec. func-defs from docstring (e.g. get rid of self) +) NOTE_TEMPLATE = """ .. _{{id}}: @@ -80,9 +82,7 @@ {% endif %} """ -DEFAULT_DIAGRAM_TEMPLATE = ( - "{{type_name}}\\n**{{title|wordwrap(15, wrapstring='**\\\\n**')}}**\\n{{id}}" -) +DEFAULT_DIAGRAM_TEMPLATE = "{{type_name}}\\n**{{title|wordwrap(15, wrapstring='**\\\\n**')}}**\\n{{id}}" # You can uncomment some of the following lines to override the default configuration for Sphinx-Needs. # needs_diagram_template = DEFAULT_DIAGRAM_TEMPLATE @@ -110,16 +110,71 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "title": "System", "content": "plantuml", "prefix": "S_", "color": "#BFD8D2", "style": "card"}, + { + "directive": "sys", + "title": "System", + "content": "plantuml", + "prefix": "S_", + "color": "#BFD8D2", + "style": "card", + }, # Normal types - {"directive": "req", "title": "Requirement", "prefix": "R_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "S_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "I_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "T_", "color": "#DCB239", "style": "node"}, - {"directive": "feature", "title": "Feature", "prefix": "F_", "color": "#FFCC00", "style": "node"}, - {"directive": "user", "title": "User", "prefix": "U_", "color": "#777777", "style": "node"}, - {"directive": "action", "title": "Action", "prefix": "A_", "color": "#FFCC00", "style": "node"}, - {"directive": "milestone", "title": "Milestone", "prefix": "M_", "color": "#FF3333", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "R_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "S_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "I_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "T_", + "color": "#DCB239", + "style": "node", + }, + { + "directive": "feature", + "title": "Feature", + "prefix": "F_", + "color": "#FFCC00", + "style": "node", + }, + { + "directive": "user", + "title": "User", + "prefix": "U_", + "color": "#777777", + "style": "node", + }, + { + "directive": "action", + "title": "Action", + "prefix": "A_", + "color": "#FFCC00", + "style": "node", + }, + { + "directive": "milestone", + "title": "Milestone", + "prefix": "M_", + "color": "#FF3333", + "style": "node", + }, ] needs_extra_links = [ @@ -208,7 +263,9 @@ needs_id_required = False # needs_css = "dark.css" -local_plantuml_path = os.path.join(os.path.dirname(__file__), "utils", "plantuml-1.2022.14.jar") +local_plantuml_path = os.path.join( + os.path.dirname(__file__), "utils", "plantuml-1.2022.14.jar" +) plantuml = f"java -Djava.awt.headless=true -jar {local_plantuml_path}" # plantuml_output_format = 'png' @@ -246,7 +303,10 @@ "grid": "simple_side_right_partial", "layout": { "head": ['**<>** for *<>*'], - "meta": ['**status**: <>', '**author**: <>'], + "meta": [ + '**status**: <>', + '**author**: <>', + ], "side": ['<>'], }, }, @@ -450,14 +510,22 @@ def custom_defined_func(): # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, "needstestdocs.tex", "needs test docs Documentation", "team useblocks", "manual"), + ( + master_doc, + "needstestdocs.tex", + "needs test docs Documentation", + "team useblocks", + "manual", + ), ] # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [(master_doc, "needstestdocs", "needs test docs Documentation", [author], 1)] +man_pages = [ + (master_doc, "needstestdocs", "needs test docs Documentation", [author], 1) +] # -- Options for Texinfo output ------------------------------------------- @@ -478,7 +546,11 @@ def custom_defined_func(): # contains different constraints needs_constraints = { - "critical": {"check_0": "'critical' in tags", "check_1": "'SECURITY_REQ' in links", "severity": "CRITICAL"}, + "critical": { + "check_0": "'critical' in tags", + "check_1": "'SECURITY_REQ' in links", + "severity": "CRITICAL", + }, "security": {"check_0": "'security' in tags", "severity": "HIGH"}, "team": {"check_0": 'author == "Bob"', "severity": "LOW"}, } diff --git a/noxfile.py b/noxfile.py index 467cb545e..a67fef8da 100644 --- a/noxfile.py +++ b/noxfile.py @@ -72,7 +72,15 @@ def pre_commit(session): def linkcheck(session): session.install(".[docs]") with session.chdir("docs"): - session.run("sphinx-build", "-b", "linkcheck", ".", "_build/linkcheck", *session.posargs, external=True) + session.run( + "sphinx-build", + "-b", + "linkcheck", + ".", + "_build/linkcheck", + *session.posargs, + external=True, + ) @session(python="3.11") diff --git a/performance/performance_test.py b/performance/performance_test.py index 1733f6328..c7ca7e368 100644 --- a/performance/performance_test.py +++ b/performance/performance_test.py @@ -23,7 +23,15 @@ def cli(): def start( - needs=1000, needtables=0, dummies=0, pages=1, parallel=1, keep=False, browser=False, debug=False, basic=False + needs=1000, + needtables=0, + dummies=0, + pages=1, + parallel=1, + keep=False, + browser=False, + debug=False, + basic=False, ): """ Test run implementation @@ -163,11 +171,31 @@ def start( @cli.command() -@click.option("--profile", default=[], type=str, multiple=True, help="Activates profiling for given area") -@click.option("--needs", default=[50, 10], type=int, multiple=True, help="Number of maximum needs.") -@click.option("--needtables", default=-1, type=int, help="Number of maximum needtables.") +@click.option( + "--profile", + default=[], + type=str, + multiple=True, + help="Activates profiling for given area", +) +@click.option( + "--needs", + default=[50, 10], + type=int, + multiple=True, + help="Number of maximum needs.", +) +@click.option( + "--needtables", default=-1, type=int, help="Number of maximum needtables." +) @click.option("--dummies", default=-1, type=int, help="Number of standard rst dummies.") -@click.option("--pages", default=[5, 1], type=int, multiple=True, help="Number of additional pages with needs.") +@click.option( + "--pages", + default=[5, 1], + type=int, + multiple=True, + help="Number of additional pages with needs.", +) @click.option( "--parallel", default=[1, 4], @@ -177,9 +205,19 @@ def start( ) @click.option("--keep", is_flag=True, help="Keeps the temporary src and build folders") @click.option("--browser", is_flag=True, help="Opens the project in your browser") -@click.option("--snakeviz", is_flag=True, help="Opens snakeviz view for measured profiles in browser") -@click.option("--debug", is_flag=True, help="Prints more information, incl. sphinx build output") -@click.option("--basic", is_flag=True, help="Use only default config of Sphinx-Needs (e.g. no extra options)") +@click.option( + "--snakeviz", + is_flag=True, + help="Opens snakeviz view for measured profiles in browser", +) +@click.option( + "--debug", is_flag=True, help="Prints more information, incl. sphinx build output" +) +@click.option( + "--basic", + is_flag=True, + help="Use only default config of Sphinx-Needs (e.g. no extra options)", +) def series( profile, needs, diff --git a/pyproject.toml b/pyproject.toml index 054de6c18..23fe436da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -101,11 +101,19 @@ markers = [ "jstest: marks tests as JavaScript test (deselect with '-m \"not jstest\"')", ] -[tool.black] -line-length = 120 - -[tool.isort] -profile = "black" +[tool.ruff] +extend-select = [ + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "I", # isort + "ICN", # flake8-import-conventions + "ISC", # flake8-implicit-str-concat + "N", # pep8-naming + "RUF", # Ruff-specific rules + "SIM", # flake8-simplify + "UP", # pyupgrade +] +extend-ignore = ["B904", "ISC001", "ICN001", "N818", "RUF005", "RUF013", "RUF012", "SIM108", "SIM118"] [tool.mypy] files = "sphinx_needs" diff --git a/sphinx_needs/api/configuration.py b/sphinx_needs/api/configuration.py index 8b06ab045..1197cd8c4 100644 --- a/sphinx_needs/api/configuration.py +++ b/sphinx_needs/api/configuration.py @@ -37,7 +37,12 @@ def get_need_types(app: Sphinx) -> list[str]: def add_need_type( - app: Sphinx, directive: str, title: str, prefix: str, color: str = "#ffffff", style: str = "node" + app: Sphinx, + directive: str, + title: str, + prefix: str, + color: str = "#ffffff", + style: str = "node", ) -> None: """ Adds a new need_type to the configuration. @@ -68,7 +73,15 @@ def add_need_type( if directive in type_names: raise NeedsApiConfigException(f"{directive} already exists as need type") - needs_types.append({"directive": directive, "title": title, "prefix": prefix, "color": color, "style": style}) + needs_types.append( + { + "directive": directive, + "title": title, + "prefix": prefix, + "color": color, + "style": style, + } + ) app.add_directive(directive, sphinx_needs.directives.need.NeedDirective) @@ -93,7 +106,9 @@ def add_extra_option(app: Sphinx, name: str) -> None: NEEDS_CONFIG.extra_options[name] = directives.unchanged -def add_dynamic_function(app: Sphinx, function: DynamicFunction, name: str | None = None) -> None: +def add_dynamic_function( + app: Sphinx, function: DynamicFunction, name: str | None = None +) -> None: """ Registers a new dynamic function for sphinx-needs. @@ -124,7 +139,12 @@ def my_function(app, need, needs, *args, **kwargs): WarningCheck = Callable[[NeedsInfoType, SphinxLoggerAdapter], bool] -def add_warning(app: Sphinx, name: str, function: WarningCheck | None = None, filter_string: str | None = None) -> None: +def add_warning( + app: Sphinx, + name: str, + function: WarningCheck | None = None, + filter_string: str | None = None, +) -> None: """ Registers a warning. @@ -137,11 +157,14 @@ def add_warning(app: Sphinx, name: str, function: WarningCheck | None = None, fi :return: None """ if function is None and filter_string is None: - raise NeedsApiConfigException("Function or filter_string must be given for add_warning_func") + raise NeedsApiConfigException( + "Function or filter_string must be given for add_warning_func" + ) if function is not None and filter_string is not None: raise NeedsApiConfigException( - "For add_warning_func only function or filter_string is allowed to be set, " "not both." + "For add_warning_func only function or filter_string is allowed to be set, " + "not both." ) warning_check = function or filter_string diff --git a/sphinx_needs/api/need.py b/sphinx_needs/api/need.py index 1a1b87f8b..32dec8513 100644 --- a/sphinx_needs/api/need.py +++ b/sphinx_needs/api/need.py @@ -152,8 +152,8 @@ def run(): configured_need_types = [ntype["directive"] for ntype in types] if need_type not in configured_need_types: logger.warning( - "Couldn't create need {}. Reason: The need-type (i.e. `{}`) is not set " - "in the project's 'need_types' configuration in conf.py. [needs]".format(id, need_type), + f"Couldn't create need {id}. Reason: The need-type (i.e. `{need_type}`) is not set " + "in the project's 'need_types' configuration in conf.py. [needs]", type="needs", ) @@ -161,7 +161,9 @@ def run(): if ntype["directive"] == need_type: type_name = ntype["title"] type_prefix = ntype["prefix"] - type_color = ntype["color"] or "#000000" # if no color set up user in config + type_color = ( + ntype["color"] or "#000000" + ) # if no color set up user in config type_style = ntype["style"] or "node" # if no style set up user in config found = True break @@ -184,7 +186,7 @@ def run(): if id is None and needs_config.id_required: raise NeedsNoIdException( "An id is missing for this need and must be set, because 'needs_id_required' " - "is set to True in conf.py. Need '{}' in {} ({})".format(title, docname, lineno) + f"is set to True in conf.py. Need '{title}' in {docname} ({lineno})" ) if id is None: @@ -193,13 +195,18 @@ def run(): need_id = id if needs_config.id_regex and not re.match(needs_config.id_regex, need_id): - raise NeedsInvalidException(f"Given ID '{need_id}' does not match configured regex '{needs_config.id_regex}'") + raise NeedsInvalidException( + f"Given ID '{need_id}' does not match configured regex '{needs_config.id_regex}'" + ) # Handle status # Check if status is in needs_statuses. If not raise an error. - if needs_config.statuses and status not in [stat["name"] for stat in needs_config.statuses]: + if needs_config.statuses and status not in [ + stat["name"] for stat in needs_config.statuses + ]: raise NeedsStatusNotAllowed( - f"Status {status} of need id {need_id} is not allowed " "by config value 'needs_statuses'." + f"Status {status} of need id {need_id} is not allowed " + "by config value 'needs_statuses'." ) if tags is None: @@ -212,7 +219,8 @@ def run(): for i in range(len(tags)): if len(tags[i]) == 0 or tags[i].isspace(): logger.warning( - f"Scruffy tag definition found in need {need_id}. " "Defined tag contains spaces only. [needs]", + f"Scruffy tag definition found in need {need_id}. " + "Defined tag contains spaces only. [needs]", type="needs", ) else: @@ -225,7 +233,8 @@ def run(): needs_tags = [tag["name"] for tag in needs_config.tags] if tag not in needs_tags: raise NeedsTagNotAllowed( - f"Tag {tag} of need id {need_id} is not allowed " "by config value 'needs_tags'." + f"Tag {tag} of need id {need_id} is not allowed " + "by config value 'needs_tags'." ) # This may have cut also dynamic function strings, as they can contain , as well. # So let put them together again @@ -237,7 +246,9 @@ def run(): if len(constraints) > 0: # tags should be a string, but it can also be already a list,which can be used. if isinstance(constraints, str): - constraints = [constraint.strip() for constraint in re.split("[;,]", constraints)] + constraints = [ + constraint.strip() for constraint in re.split("[;,]", constraints) + ] new_constraints = [] # Shall contain only valid constraints for i in range(len(constraints)): @@ -356,9 +367,9 @@ def run(): for keyword in kwargs: if keyword not in needs_extra_option_names and keyword not in link_names: raise NeedsInvalidOption( - "Unknown Option {}. " + f"Unknown Option {keyword}. " "Use needs_extra_options or needs_extra_links in conf.py" - "to define this option.".format(keyword) + "to define this option." ) # Merge links @@ -366,11 +377,15 @@ def run(): for link_type in needs_config.extra_links: # Check, if specific link-type got some arguments during method call - if link_type["option"] not in kwargs and link_type["option"] not in needs_global_options: + if ( + link_type["option"] not in kwargs + and link_type["option"] not in needs_global_options + ): # if not we set no links, but entry in needS_info must be there links = [] elif link_type["option"] in needs_global_options and ( - link_type["option"] not in kwargs or len(str(kwargs[link_type["option"]])) == 0 + link_type["option"] not in kwargs + or len(str(kwargs[link_type["option"]])) == 0 ): # If it is in global option, value got already set during prior handling of them links_string = needs_info[link_type["option"]] @@ -585,7 +600,9 @@ def _prepare_template(app: Sphinx, needs_info, template_key: str) -> str: template_folder = os.path.join(app.srcdir, template_folder) if not os.path.isdir(template_folder): - raise NeedsTemplateException(f"Template folder does not exist: {template_folder}") + raise NeedsTemplateException( + f"Template folder does not exist: {template_folder}" + ) template_file_name = needs_info[template_key] + ".need" template_path = os.path.join(template_folder, template_file_name) @@ -600,7 +617,9 @@ def _prepare_template(app: Sphinx, needs_info, template_key: str) -> str: return new_content -def _render_template(content: str, docname: str, lineno: int, state: RSTState) -> nodes.Element: +def _render_template( + content: str, docname: str, lineno: int, state: RSTState +) -> nodes.Element: rst = StringList() for line in content.split("\n"): rst.append(line, docname, lineno) @@ -610,7 +629,9 @@ def _render_template(content: str, docname: str, lineno: int, state: RSTState) - return node_need_content -def _render_plantuml_template(content: str, docname: str, lineno: int, state: RSTState) -> nodes.Element: +def _render_plantuml_template( + content: str, docname: str, lineno: int, state: RSTState +) -> nodes.Element: rst = StringList() rst.append(".. needuml::", docname, lineno) rst.append("", docname, lineno) # Empty option line for needuml @@ -636,7 +657,8 @@ def _read_in_links(links_string: str | list[str]) -> list[str]: for link in link_list: if link.isspace(): logger.warning( - f"Grubby link definition found in need {id}. " "Defined link contains spaces only. [needs]", + f"Grubby link definition found in need {id}. " + "Defined link contains spaces only. [needs]", type="needs", ) else: @@ -648,7 +670,13 @@ def _read_in_links(links_string: str | list[str]) -> list[str]: return _fix_list_dyn_func(links) -def make_hashed_id(app: Sphinx, need_type: str, full_title: str, content: str, id_length: int | None = None) -> str: +def make_hashed_id( + app: Sphinx, + need_type: str, + full_title: str, + content: str, + id_length: int | None = None, +) -> str: """ Creates an ID based on title or need. @@ -671,7 +699,9 @@ def make_hashed_id(app: Sphinx, need_type: str, full_title: str, content: str, i type_prefix = ntype["prefix"] break if type_prefix is None: - raise NeedsInvalidException(f"Given need_type {need_type} is unknown. File {app.env.docname}") + raise NeedsInvalidException( + f"Given need_type {need_type} is unknown. File {app.env.docname}" + ) hashable_content = full_title or "\n".join(content) hashed_id = hashlib.sha1(hashable_content.encode("UTF-8")).hexdigest().upper() @@ -764,11 +794,15 @@ def _merge_global_options(app: Sphinx, needs_info, global_options) -> None: for single_value in values: if len(single_value) < 2 or len(single_value) > 3: - raise NeedsInvalidException(f"global option tuple has wrong amount of parameters: {key}") + raise NeedsInvalidException( + f"global option tuple has wrong amount of parameters: {key}" + ) if filter_single_need(needs_info, config, single_value[1]): # Set value, if filter has matched needs_info[key] = single_value[0] - elif len(single_value) == 3 and (key not in needs_info.keys() or len(str(needs_info[key])) > 0): + elif len(single_value) == 3 and ( + key not in needs_info.keys() or len(str(needs_info[key])) > 0 + ): # Otherwise set default, but only if no value was set before or value is "" and a default is defined needs_info[key] = single_value[2] else: diff --git a/sphinx_needs/builder.py b/sphinx_needs/builder.py index e1eaf7994..b4ebea207 100644 --- a/sphinx_needs/builder.py +++ b/sphinx_needs/builder.py @@ -50,7 +50,9 @@ def write( if not SphinxNeedsData(self.env).has_export_filters: return LOGGER.warning( - "At least one use of `export_id` directive option, requires a slower build", type="needs", subtype="build" + "At least one use of `export_id` directive option, requires a slower build", + type="needs", + subtype="build", ) return super().write(build_docnames, updated_docnames, method) @@ -70,7 +72,9 @@ def finish(self) -> None: # check if needs.json file exists in conf.py directory needs_json = os.path.join(self.srcdir, "needs.json") if os.path.exists(needs_json): - LOGGER.info("needs.json found, but will not be used because needs_file not configured.") + LOGGER.info( + "needs.json found, but will not be used because needs_file not configured." + ) # Clean needs_list from already stored needs of the current version. # This is needed as needs could have been removed from documentation and if this is the case, @@ -170,7 +174,9 @@ def finish(self) -> None: post_process_needs_data(self.app) data = SphinxNeedsData(self.env) - needs = data.get_or_create_needs().values() # We need a list of needs for later filter checks + needs = ( + data.get_or_create_needs().values() + ) # We need a list of needs for later filter checks version = getattr(self.env.config, "version", "unset") needs_config = NeedsSphinxConfig(self.env.config) filter_string = needs_config.builder_filter diff --git a/sphinx_needs/config.py b/sphinx_needs/config.py index a988074fe..785436f7e 100644 --- a/sphinx_needs/config.py +++ b/sphinx_needs/config.py @@ -26,7 +26,9 @@ class Config: def __init__(self) -> None: self._extra_options: dict[str, Callable[[str], Any]] = {} - self._warnings: dict[str, str | Callable[[NeedsInfoType, SphinxLoggerAdapter], bool]] = {} + self._warnings: dict[ + str, str | Callable[[NeedsInfoType, SphinxLoggerAdapter], bool] + ] = {} def clear(self) -> None: self._extra_options = {} @@ -44,7 +46,9 @@ def extra_options(self) -> dict[str, Callable[[str], Any]]: return self._extra_options @property - def warnings(self) -> dict[str, str | Callable[[NeedsInfoType, SphinxLoggerAdapter], bool]]: + def warnings( + self + ) -> dict[str, str | Callable[[NeedsInfoType, SphinxLoggerAdapter], bool]]: """Warning handlers that are added by the user, then called at the end of the build. """ @@ -130,58 +134,117 @@ def __setattr__(self, name: str, value: Any) -> None: metadata={"rebuild": "html", "types": ()}, ) """Custom user need types""" - include_needs: bool = field(default=True, metadata={"rebuild": "html", "types": (bool,)}) - need_name: str = field(default="Need", metadata={"rebuild": "html", "types": (str,)}) - spec_name: str = field(default="Specification", metadata={"rebuild": "html", "types": (str,)}) - id_prefix_needs: str = field(default="", metadata={"rebuild": "html", "types": (str,)}) - id_prefix_specs: str = field(default="", metadata={"rebuild": "html", "types": (str,)}) + include_needs: bool = field( + default=True, metadata={"rebuild": "html", "types": (bool,)} + ) + need_name: str = field( + default="Need", metadata={"rebuild": "html", "types": (str,)} + ) + spec_name: str = field( + default="Specification", metadata={"rebuild": "html", "types": (str,)} + ) + id_prefix_needs: str = field( + default="", metadata={"rebuild": "html", "types": (str,)} + ) + id_prefix_specs: str = field( + default="", metadata={"rebuild": "html", "types": (str,)} + ) id_length: int = field(default=5, metadata={"rebuild": "html", "types": (int,)}) - id_from_title: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - specs_show_needlist: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - id_required: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - id_regex: str = field(default="^[A-Z0-9_]{5,}", metadata={"rebuild": "html", "types": ()}) - show_link_type: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - show_link_title: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - show_link_id: bool = field(default=True, metadata={"rebuild": "html", "types": (bool,)}) + id_from_title: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + specs_show_needlist: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + id_required: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + id_regex: str = field( + default="^[A-Z0-9_]{5,}", metadata={"rebuild": "html", "types": ()} + ) + show_link_type: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + show_link_title: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + show_link_id: bool = field( + default=True, metadata={"rebuild": "html", "types": (bool,)} + ) file: None | str = field(default=None, metadata={"rebuild": "html", "types": ()}) table_columns: str = field( - default="ID;TITLE;STATUS;TYPE;OUTGOING;TAGS", metadata={"rebuild": "html", "types": (str,)} - ) - table_style: str = field(default="DATATABLES", metadata={"rebuild": "html", "types": (str,)}) - role_need_template: str = field(default="{title} ({id})", metadata={"rebuild": "html", "types": (str,)}) - role_need_max_title_length: int = field(default=30, metadata={"rebuild": "html", "types": (int,)}) - extra_options: list[str] = field(default_factory=list, metadata={"rebuild": "html", "types": (list,)}) - title_optional: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - max_title_length: int = field(default=-1, metadata={"rebuild": "html", "types": (int,)}) - title_from_content: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) + default="ID;TITLE;STATUS;TYPE;OUTGOING;TAGS", + metadata={"rebuild": "html", "types": (str,)}, + ) + table_style: str = field( + default="DATATABLES", metadata={"rebuild": "html", "types": (str,)} + ) + role_need_template: str = field( + default="{title} ({id})", metadata={"rebuild": "html", "types": (str,)} + ) + role_need_max_title_length: int = field( + default=30, metadata={"rebuild": "html", "types": (int,)} + ) + extra_options: list[str] = field( + default_factory=list, metadata={"rebuild": "html", "types": (list,)} + ) + title_optional: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + max_title_length: int = field( + default=-1, metadata={"rebuild": "html", "types": (int,)} + ) + title_from_content: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) diagram_template: str = field( default=DEFAULT_DIAGRAM_TEMPLATE, metadata={"rebuild": "html", "types": (str,)}, ) - functions: list[Callable[..., Any]] = field(default_factory=list, metadata={"rebuild": "html", "types": (list,)}) - global_options: dict[str, Any] = field(default_factory=dict, metadata={"rebuild": "html", "types": (dict,)}) - duration_option: str = field(default="duration", metadata={"rebuild": "html", "types": (str,)}) - completion_option: str = field(default="completion", metadata={"rebuild": "html", "types": (str,)}) - needextend_strict: bool = field(default=True, metadata={"rebuild": "html", "types": (bool,)}) - statuses: list[dict[str, str]] = field(default_factory=list, metadata={"rebuild": "html", "types": ()}) + functions: list[Callable[..., Any]] = field( + default_factory=list, metadata={"rebuild": "html", "types": (list,)} + ) + global_options: dict[str, Any] = field( + default_factory=dict, metadata={"rebuild": "html", "types": (dict,)} + ) + duration_option: str = field( + default="duration", metadata={"rebuild": "html", "types": (str,)} + ) + completion_option: str = field( + default="completion", metadata={"rebuild": "html", "types": (str,)} + ) + needextend_strict: bool = field( + default=True, metadata={"rebuild": "html", "types": (bool,)} + ) + statuses: list[dict[str, str]] = field( + default_factory=list, metadata={"rebuild": "html", "types": ()} + ) """If given, only the defined status are allowed. Values needed for each status: * name * description Example: [{"name": "open", "description": "open status"}, {...}, {...}] """ - tags: list[dict[str, str]] = field(default_factory=list, metadata={"rebuild": "html", "types": (list,)}) + tags: list[dict[str, str]] = field( + default_factory=list, metadata={"rebuild": "html", "types": (list,)} + ) """If given, only the defined tags are allowed. Values needed for each tag: * name * description Example: [{"name": "new", "description": "new needs"}, {...}, {...}] """ - css: str = field(default="modern.css", metadata={"rebuild": "html", "types": (str,)}) + css: str = field( + default="modern.css", metadata={"rebuild": "html", "types": (str,)} + ) """Path of css file, which shall be used for need style""" - part_prefix: str = field(default="→\xa0", metadata={"rebuild": "html", "types": (str,)}) + part_prefix: str = field( + default="→\xa0", metadata={"rebuild": "html", "types": (str,)} + ) """Prefix for need_part output in tables""" - extra_links: list[dict[str, Any]] = field(default_factory=list, metadata={"rebuild": "html", "types": ()}) + extra_links: list[dict[str, Any]] = field( + default_factory=list, metadata={"rebuild": "html", "types": ()} + ) """List of additional links, which can be used by setting related option Values needed for each new link: * option (will also be the option name) @@ -190,48 +253,97 @@ def __setattr__(self, name: str, value: Any) -> None: * color (used for needflow. Default: #000000) Example: [{"name": "blocks, "incoming": "is blocked by", "copy_link": True, "color": "#ffcc00"}] """ - report_dead_links: bool = field(default=True, metadata={"rebuild": "html", "types": (bool,)}) + report_dead_links: bool = field( + default=True, metadata={"rebuild": "html", "types": (bool,)} + ) """DEPRECATED: Use ``suppress_warnings = ["needs.link_outgoing"]`` instead.""" - filter_data: dict[str, Any] = field(default_factory=dict, metadata={"rebuild": "html", "types": ()}) - allow_unsafe_filters: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - flow_show_links: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - flow_link_types: list[str] = field(default_factory=lambda: ["links"], metadata={"rebuild": "html", "types": ()}) + filter_data: dict[str, Any] = field( + default_factory=dict, metadata={"rebuild": "html", "types": ()} + ) + allow_unsafe_filters: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + flow_show_links: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + flow_link_types: list[str] = field( + default_factory=lambda: ["links"], metadata={"rebuild": "html", "types": ()} + ) """Defines the link_types to show in a needflow diagram.""" - warnings: dict[str, Any] = field(default_factory=dict, metadata={"rebuild": "html", "types": ()}) - warnings_always_warn: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - layouts: dict[str, dict[str, Any]] = field(default_factory=dict, metadata={"rebuild": "html", "types": ()}) - default_layout: str = field(default="clean", metadata={"rebuild": "html", "types": (str,)}) - default_style: None | str = field(default=None, metadata={"rebuild": "html", "types": ()}) - flow_configs: dict[str, str] = field(default_factory=dict, metadata={"rebuild": "html", "types": ()}) - template_folder: str = field(default="needs_templates/", metadata={"rebuild": "html", "types": (str,)}) - services: dict[str, dict[str, Any]] = field(default_factory=dict, metadata={"rebuild": "html", "types": ()}) - service_all_data: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - debug_no_external_calls: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - external_needs: list[dict[str, Any]] = field(default_factory=list, metadata={"rebuild": "html", "types": ()}) + warnings: dict[str, Any] = field( + default_factory=dict, metadata={"rebuild": "html", "types": ()} + ) + warnings_always_warn: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + layouts: dict[str, dict[str, Any]] = field( + default_factory=dict, metadata={"rebuild": "html", "types": ()} + ) + default_layout: str = field( + default="clean", metadata={"rebuild": "html", "types": (str,)} + ) + default_style: None | str = field( + default=None, metadata={"rebuild": "html", "types": ()} + ) + flow_configs: dict[str, str] = field( + default_factory=dict, metadata={"rebuild": "html", "types": ()} + ) + template_folder: str = field( + default="needs_templates/", metadata={"rebuild": "html", "types": (str,)} + ) + services: dict[str, dict[str, Any]] = field( + default_factory=dict, metadata={"rebuild": "html", "types": ()} + ) + service_all_data: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + debug_no_external_calls: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + external_needs: list[dict[str, Any]] = field( + default_factory=list, metadata={"rebuild": "html", "types": ()} + ) """Reference external needs, outside of the documentation.""" - builder_filter: str = field(default="is_external==False", metadata={"rebuild": "html", "types": (str,)}) + builder_filter: str = field( + default="is_external==False", metadata={"rebuild": "html", "types": (str,)} + ) table_classes: list[str] = field( - default_factory=lambda: NEEDS_TABLES_CLASSES, metadata={"rebuild": "html", "types": (list,)} + default_factory=lambda: NEEDS_TABLES_CLASSES, + metadata={"rebuild": "html", "types": (list,)}, ) """Additional classes to set for needs and needtable.""" string_links: dict[str, dict[str, Any]] = field( default_factory=dict, metadata={"rebuild": "html", "types": (dict,)} ) - build_json: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) + build_json: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) """If True, the JSON needs file should be built.""" - reproducible_json: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) + reproducible_json: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) """If True, the JSON needs file should be idempotent for multiple builds fo the same documentation.""" - build_needumls: str = field(default="", metadata={"rebuild": "html", "types": (str,)}) - permalink_file: str = field(default="permalink.html", metadata={"rebuild": "html", "types": (str,)}) + build_needumls: str = field( + default="", metadata={"rebuild": "html", "types": (str,)} + ) + permalink_file: str = field( + default="permalink.html", metadata={"rebuild": "html", "types": (str,)} + ) """Permalink related config values. path to permalink.html; absolute path from web-root """ - permalink_data: str = field(default="needs.json", metadata={"rebuild": "html", "types": (str,)}) + permalink_data: str = field( + default="needs.json", metadata={"rebuild": "html", "types": (str,)} + ) """path to needs.json relative to permalink.html""" - report_template: str = field(default="", metadata={"rebuild": "html", "types": (str,)}) + report_template: str = field( + default="", metadata={"rebuild": "html", "types": (str,)} + ) """path to needs_report_template file which is based on the conf.py directory.""" - constraints: dict[str, dict[str, str]] = field(default_factory=dict, metadata={"rebuild": "html", "types": (dict,)}) + constraints: dict[str, dict[str, str]] = field( + default_factory=dict, metadata={"rebuild": "html", "types": (dict,)} + ) """Mapping of constraint name, to check name, to filter string. There are also some special keys for a constraint: @@ -242,21 +354,35 @@ def __setattr__(self, name: str, value: Any) -> None: default_factory=dict, metadata={"rebuild": "html", "types": (dict,)} ) """Mapping of constraint severity to what to do if a constraint is not fulfilled.""" - constraints_failed_color: str = field(default="", metadata={"rebuild": "html", "types": (str,)}) + constraints_failed_color: str = field( + default="", metadata={"rebuild": "html", "types": (str,)} + ) """DEPRECATED: Use constraint_failed_options instead.""" # add variants option - variants: dict[str, str] = field(default_factory=dict, metadata={"rebuild": "html", "types": (dict,)}) - variant_options: list[str] = field(default_factory=list, metadata={"rebuild": "html", "types": (list,)}) + variants: dict[str, str] = field( + default_factory=dict, metadata={"rebuild": "html", "types": (dict,)} + ) + variant_options: list[str] = field( + default_factory=list, metadata={"rebuild": "html", "types": (list,)} + ) # add render context option - render_context: dict[str, Any] = field(default_factory=dict, metadata={"rebuild": "html", "types": (dict,)}) + render_context: dict[str, Any] = field( + default_factory=dict, metadata={"rebuild": "html", "types": (dict,)} + ) """Jinja context for rendering templates""" - debug_measurement: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) + debug_measurement: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) # add config for needs_id_builder - build_json_per_id: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)}) - build_json_per_id_path: str = field(default="needs_id", metadata={"rebuild": "html", "types": (str,)}) + build_json_per_id: bool = field( + default=False, metadata={"rebuild": "html", "types": (bool,)} + ) + build_json_per_id_path: str = field( + default="needs_id", metadata={"rebuild": "html", "types": (str,)} + ) @classmethod def add_config_values(cls, app: Sphinx) -> None: @@ -267,7 +393,9 @@ def add_config_values(cls, app: Sphinx) -> None: elif item.default is not MISSING: default = item.default else: - raise Exception(f"Config item {item.name} has no default value or factory.") + raise Exception( + f"Config item {item.name} has no default value or factory." + ) app.add_config_value( f"needs_{item.name}", default, diff --git a/sphinx_needs/data.py b/sphinx_needs/data.py index abea4ce70..a36e362e3 100644 --- a/sphinx_needs/data.py +++ b/sphinx_needs/data.py @@ -592,7 +592,9 @@ def get_or_create_umls(self) -> dict[str, NeedsUmlType]: return self.env.needs_all_needumls -def merge_data(_app: Sphinx, env: BuildEnvironment, _docnames: list[str], other: BuildEnvironment) -> None: +def merge_data( + _app: Sphinx, env: BuildEnvironment, _docnames: list[str], other: BuildEnvironment +) -> None: """ Performs data merge of parallel executed workers. Used only for parallel builds. @@ -621,14 +623,17 @@ def _merge(name: str, is_complex_dict: bool = False) -> None: for other_key, other_value in other_objects.items(): # other_value is a list from here on! if other_key in objects: - objects[other_key] = list(set(objects[other_key]) | set(other_value)) + objects[other_key] = list( + set(objects[other_key]) | set(other_value) + ) else: objects[other_key] = other_value elif isinstance(other_objects, list) and isinstance(objects, list): objects = list(set(objects) | set(other_objects)) else: raise TypeError( - f'Objects to "merge" must be dict or list, ' f"not {type(other_objects)} and {type(objects)}" + f'Objects to "merge" must be dict or list, ' + f"not {type(other_objects)} and {type(objects)}" ) _merge("needs_all_docs", is_complex_dict=True) diff --git a/sphinx_needs/debug.py b/sphinx_needs/debug.py index 1fca7239b..ee426a076 100644 --- a/sphinx_needs/debug.py +++ b/sphinx_needs/debug.py @@ -18,14 +18,18 @@ from sphinx.application import Sphinx TIME_MEASUREMENTS: dict[str, Any] = {} # Stores the timing results -EXECUTE_TIME_MEASUREMENTS = False # Will be used to de/activate measurements. Set during a Sphinx Event +EXECUTE_TIME_MEASUREMENTS = ( + False # Will be used to de/activate measurements. Set during a Sphinx Event +) START_TIME = 0.0 T = TypeVar("T", bound=Callable[..., Any]) -def measure_time(category: str | None = None, source: str = "internal", name: str | None = None) -> Callable[[T], T]: +def measure_time( + category: str | None = None, source: str = "internal", name: str | None = None +) -> Callable[[T], T]: """ Decorator for measuring the needed execution time of a specific function. @@ -108,9 +112,13 @@ def wrapper(*args: list[object], **kwargs: dict[object, object]) -> Any: runtime_dict["max"] = runtime runtime_dict["max_params"] = { # Store parameters as a shorten string "args": str([str(arg)[:80] for arg in args]), - "kwargs": str({key: str(value)[:80] for key, value in kwargs.items()}), + "kwargs": str( + {key: str(value)[:80] for key, value in kwargs.items()} + ), } - runtime_dict["min_max_spread"] = runtime_dict["max"] / runtime_dict["min"] * 100 + runtime_dict["min_max_spread"] = ( + runtime_dict["max"] / runtime_dict["min"] * 100 + ) runtime_dict["avg"] = runtime_dict["overall"] / runtime_dict["amount"] return result @@ -119,7 +127,12 @@ def wrapper(*args: list[object], **kwargs: dict[object, object]) -> Any: return inner -def measure_time_func(func: T, category: str | None = None, source: str = "internal", name: str | None = None) -> T: +def measure_time_func( + func: T, + category: str | None = None, + source: str = "internal", + name: str | None = None, +) -> T: """Wrapper for measuring the needed execution time of a specific function. Usage as function:: @@ -154,7 +167,9 @@ def store_timing_results_json(outdir: str, build_data: dict[str, Any]) -> None: def store_timing_results_html(outdir: str, build_data: dict[str, Any]) -> None: - jinja_env = Environment(loader=PackageLoader("sphinx_needs"), autoescape=select_autoescape()) + jinja_env = Environment( + loader=PackageLoader("sphinx_needs"), autoescape=select_autoescape() + ) template = jinja_env.get_template("time_measurements.html") out_file = Path(outdir) / "debug_measurement.html" with open(out_file, "w", encoding="utf-8") as f: diff --git a/sphinx_needs/diagrams_common.py b/sphinx_needs/diagrams_common.py index 15de4321c..0eced3edb 100644 --- a/sphinx_needs/diagrams_common.py +++ b/sphinx_needs/diagrams_common.py @@ -114,7 +114,9 @@ def add_config(config: str) -> str: uml = "" if config and len(config) >= 3: # Remove all empty lines - config = "\n".join([line.strip() for line in config.split("\n") if line.strip()]) + config = "\n".join( + [line.strip() for line in config.split("\n") if line.strip()] + ) uml += "\n' Config\n\n" uml += config uml += "\n\n" @@ -125,13 +127,27 @@ def get_filter_para(node_element: NeedsFilteredBaseType) -> nodes.paragraph: """Return paragraph containing the used filter description""" para = nodes.paragraph() filter_text = "Used filter:" - filter_text += " status(%s)" % " OR ".join(node_element["status"]) if len(node_element["status"]) > 0 else "" + filter_text += ( + " status(%s)" % " OR ".join(node_element["status"]) + if len(node_element["status"]) > 0 + else "" + ) if len(node_element["status"]) > 0 and len(node_element["tags"]) > 0: filter_text += " AND " - filter_text += " tags(%s)" % " OR ".join(node_element["tags"]) if len(node_element["tags"]) > 0 else "" - if (len(node_element["status"]) > 0 or len(node_element["tags"]) > 0) and len(node_element["types"]) > 0: + filter_text += ( + " tags(%s)" % " OR ".join(node_element["tags"]) + if len(node_element["tags"]) > 0 + else "" + ) + if (len(node_element["status"]) > 0 or len(node_element["tags"]) > 0) and len( + node_element["types"] + ) > 0: filter_text += " AND " - filter_text += " types(%s)" % " OR ".join(node_element["types"]) if len(node_element["types"]) > 0 else "" + filter_text += ( + " types(%s)" % " OR ".join(node_element["types"]) + if len(node_element["types"]) > 0 + else "" + ) filter_node = nodes.emphasis(filter_text, filter_text) para += filter_node @@ -152,7 +168,9 @@ def get_debug_container(puml_node: nodes.Element) -> nodes.container: return debug_container -def calculate_link(app: Sphinx, need_info: NeedsPartsInfoType, _fromdocname: str) -> str: +def calculate_link( + app: Sphinx, need_info: NeedsPartsInfoType, _fromdocname: str +) -> str: """ Link calculation All links we can get from docutils functions will be relative. @@ -168,7 +186,9 @@ def calculate_link(app: Sphinx, need_info: NeedsPartsInfoType, _fromdocname: str builder = app.builder try: if need_info["is_external"]: - assert need_info["external_url"] is not None, "external_url must be set for external needs" + assert ( + need_info["external_url"] is not None + ), "external_url must be set for external needs" link = need_info["external_url"] # check if need_info["external_url"] is relative path parsed_url = urlparse(need_info["external_url"]) @@ -176,7 +196,12 @@ def calculate_link(app: Sphinx, need_info: NeedsPartsInfoType, _fromdocname: str # only need to add ../ or ..\ to get out of the image folder link = ".." + os.path.sep + need_info["external_url"] else: - link = "../" + builder.get_target_uri(need_info["docname"]) + "#" + need_info["target_id"] + link = ( + "../" + + builder.get_target_uri(need_info["docname"]) + + "#" + + need_info["target_id"] + ) if need_info["is_part"]: link = f"{link}.{need_info['id']}" @@ -188,7 +213,9 @@ def calculate_link(app: Sphinx, need_info: NeedsPartsInfoType, _fromdocname: str def create_legend(need_types: list[dict[str, Any]]) -> str: def create_row(need_type: dict[str, Any]) -> str: - return "\n| {color} | {name} |".format(color=need_type["color"], name=need_type["title"]) + return "\n| {color} | {name} |".format( + color=need_type["color"], name=need_type["title"] + ) rows = map(create_row, need_types) table = "|= Color |= Type |" + "".join(rows) diff --git a/sphinx_needs/directives/list2need.py b/sphinx_needs/directives/list2need.py index bbdd27643..928a73d1a 100644 --- a/sphinx_needs/directives/list2need.py +++ b/sphinx_needs/directives/list2need.py @@ -23,8 +23,12 @@ """ -LINE_REGEX = re.compile(r"(?P[^\S\n]*)\*\s*(?P.*)|[\S\*]*(?P.*)") -ID_REGEX = re.compile(r"(\((?P[^\"'=\n]+)?\))") # Exclude some chars, which are used by option list +LINE_REGEX = re.compile( + r"(?P[^\S\n]*)\*\s*(?P.*)|[\S\*]*(?P.*)" +) +ID_REGEX = re.compile( + r"(\((?P[^\"'=\n]+)?\))" +) # Exclude some chars, which are used by option list OPTION_AREA_REGEX = re.compile(r"\(\((.*)\)\)") OPTIONS_REGEX = re.compile(r"([^=,\s]*)=[\"']([^\"]*)[\"']") @@ -83,7 +87,9 @@ def run(self) -> Sequence[nodes.Node]: for x in range(0, len(types_raw_list)): types[x] = types_raw_list[x] if types[x] not in conf_types: - raise SphinxError(f"Unknown type configured: {types[x]}. Allowed are {', '.join(conf_types)}") + raise SphinxError( + f"Unknown type configured: {types[x]}. Allowed are {', '.join(conf_types)}" + ) down_links_raw = self.options.get("links-down") if down_links_raw is None or down_links_raw == "": @@ -99,7 +105,10 @@ def run(self) -> Sequence[nodes.Node]: for i, down_link_raw in enumerate(down_links_raw_list): down_links_types[i] = down_link_raw if down_link_raw not in link_types: - raise SphinxError(f"Unknown link configured: {down_link_raw}. " f"Allowed are {', '.join(link_types)}") + raise SphinxError( + f"Unknown link configured: {down_link_raw}. " + f"Allowed are {', '.join(link_types)}" + ) list_needs = [] # Storing the data in a sorted list for content_line in content_raw.split("\n"): @@ -112,23 +121,30 @@ def run(self) -> Sequence[nodes.Node]: if text: indent = len(indent) if not indent % 2 == 0: - raise IndentationError("Indentation for list must be always a multiply of 2.") + raise IndentationError( + "Indentation for list must be always a multiply of 2." + ) level = int(indent / 2) if level not in types: raise SphinxWarning( - f"No need type defined for indentation level {level}." f" Defined types {types}" + f"No need type defined for indentation level {level}." + f" Defined types {types}" ) if down_links_types and level > len(down_links_types): - raise SphinxWarning(f"Not enough links-down defined for indentation level {level}.") + raise SphinxWarning( + f"Not enough links-down defined for indentation level {level}." + ) splitted_text = text.split(delimiter) title = splitted_text[0] content = "" with suppress(IndexError): - content = delimiter.join(splitted_text[1:]) # Put the content together again + content = delimiter.join( + splitted_text[1:] + ) # Put the content together again need_id_result = ID_REGEX.search(title) if need_id_result: @@ -158,7 +174,9 @@ def run(self) -> Sequence[nodes.Node]: more_text = more_text.lstrip() if more_text.startswith(":"): more_text = f" {more_text}" - list_needs[-1]["content"] = f"{list_needs[-1]['content']}\n {more_text}" + list_needs[-1][ + "content" + ] = f"{list_needs[-1]['content']}\n {more_text}" # Finally creating the rst code overall_text = [] @@ -179,7 +197,11 @@ def run(self) -> Sequence[nodes.Node]: data = list_need need_links_down = self.get_down_needs(list_needs, index) - if down_links_types and list_need["level"] in down_links_types and need_links_down: + if ( + down_links_types + and list_need["level"] in down_links_types + and need_links_down + ): data["links_down"] = need_links_down data["links_down_type"] = down_links_types[list_need["level"]] data["set_links_down"] = True @@ -193,14 +215,19 @@ def run(self) -> Sequence[nodes.Node]: text_list = indented_text_list overall_text += text_list - self.state_machine.insert_input(overall_text, self.state_machine.document.attributes["source"]) + self.state_machine.insert_input( + overall_text, self.state_machine.document.attributes["source"] + ) return [] def make_hashed_id(self, type_prefix: str, title: str, id_length: int) -> str: hashable_content = title return "{}{}".format( - type_prefix, hashlib.sha1(hashable_content.encode("UTF-8")).hexdigest().upper()[:id_length] + type_prefix, + hashlib.sha1(hashable_content.encode("UTF-8")) + .hexdigest() + .upper()[:id_length], ) def get_down_needs(self, list_needs: list[Any], index: int) -> list[str]: diff --git a/sphinx_needs/directives/need.py b/sphinx_needs/directives/need.py index f4c527791..7863b161f 100644 --- a/sphinx_needs/directives/need.py +++ b/sphinx_needs/directives/need.py @@ -64,7 +64,17 @@ def __init__( state: RSTState, state_machine: RSTStateMachine, ): - super().__init__(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine) + super().__init__( + name, + arguments, + options, + content, + lineno, + content_offset, + block_text, + state, + state_machine, + ) self.needs_config = NeedsSphinxConfig(self.env.config) self.log = get_logger(__name__) self.full_title = self._get_full_title() @@ -109,7 +119,9 @@ def run(self) -> Sequence[nodes.Node]: content = "\n".join(self.content) status = self.options.get("status") if status: - status = status.replace("__", "") # Support for multiline options, which must use __ for empty lines + status = status.replace( + "__", "" + ) # Support for multiline options, which must use __ for empty lines tags = self.options.get("tags", "") style = self.options.get("style") layout = self.options.get("layout", "") @@ -121,7 +133,9 @@ def run(self) -> Sequence[nodes.Node]: need_extra_options = {"duration": duration, "completion": completion} for extra_link in self.needs_config.extra_links: - need_extra_options[extra_link["option"]] = self.options.get(extra_link["option"], "") + need_extra_options[extra_link["option"]] = self.options.get( + extra_link["option"], "" + ) for extra_option in NEEDS_CONFIG.extra_options: need_extra_options[extra_option] = self.options.get(extra_option, "") @@ -175,12 +189,17 @@ def read_in_links(self, name: str) -> list[str]: def make_hashed_id(self, type_prefix: str, id_length: int) -> str: hashable_content = self.full_title or "\n".join(self.content) return "{}{}".format( - type_prefix, hashlib.sha1(hashable_content.encode("UTF-8")).hexdigest().upper()[:id_length] + type_prefix, + hashlib.sha1(hashable_content.encode("UTF-8")) + .hexdigest() + .upper()[:id_length], ) @property def title_from_content(self) -> bool: - return "title_from_content" in self.options or self.needs_config.title_from_content + return ( + "title_from_content" in self.options or self.needs_config.title_from_content + ) @property def docname(self) -> str: @@ -211,8 +230,8 @@ def _get_full_title(self) -> str: if len(self.arguments) > 0: # a title was passed if "title_from_content" in self.options: self.log.warning( - 'need "{}" has :title_from_content: set, ' - "but a title was provided. (see file {}) [needs]".format(self.arguments[0], self.docname), + f'need "{self.arguments[0]}" has :title_from_content: set, ' + f"but a title was provided. (see file {self.docname}) [needs]", type="needs", location=(self.env.docname, self.lineno), ) @@ -223,7 +242,7 @@ def _get_full_title(self) -> str: raise NeedsInvalidException( ":title_from_content: set, but " "no content provided. " - "(Line {} of file {}".format(self.lineno, self.docname) + f"(Line {self.lineno} of file {self.docname}" ) return first_sentence else: @@ -260,7 +279,9 @@ def get_sections_and_signature_and_needs( if isinstance(sibling, desc_signature): # Check the child of the found signature for the text content/node. for desc_child in sibling.children: - if isinstance(desc_child, desc_name) and isinstance(desc_child.children[0], nodes.Text): + if isinstance(desc_child, desc_name) and isinstance( + desc_child.children[0], nodes.Text + ): signature = desc_child.children[0] if signature: break @@ -324,7 +345,9 @@ def analyse_need_locations(app: Sphinx, doctree: nodes.document) -> None: # Fetch values from need # Start from the target node, which is a sibling of the current need node - sections, signature, parent_needs = get_sections_and_signature_and_needs(previous_sibling(need_node)) + sections, signature, parent_needs = get_sections_and_signature_and_needs( + previous_sibling(need_node) + ) # append / set values from need if sections: @@ -410,7 +433,12 @@ def process_need_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str) - @profile("NEED_FORMAT") -def format_need_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str, found_needs_nodes: list[Need]) -> None: +def format_need_nodes( + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_needs_nodes: list[Need], +) -> None: """Replace need nodes in the document with node trees suitable for output""" env = app.env needs = SphinxNeedsData(env).get_or_create_needs() @@ -423,7 +451,9 @@ def format_need_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str, fo find_and_replace_node_content(node_need, env, need_data) for index, attribute in enumerate(node_need.attributes["classes"]): - node_need.attributes["classes"][index] = check_and_get_content(attribute, need_data, env) + node_need.attributes["classes"][index] = check_and_get_content( + attribute, need_data, env + ) layout = need_data["layout"] or NeedsSphinxConfig(app.config).default_layout @@ -441,14 +471,15 @@ def check_links(needs: dict[str, NeedsInfoType], config: NeedsSphinxConfig) -> N report_dead_links = config.report_dead_links for need in needs.values(): for link_type in extra_links: - need_link_value = ( - [need[link_type["option"]]] if isinstance(need[link_type["option"]], str) else need[link_type["option"]] # type: ignore - ) + _value = need[link_type["option"]] # type: ignore[literal-required] + need_link_value = [_value] if isinstance(_value, str) else _value for need_id_full in need_link_value: need_id_main, need_id_part = split_need_id(need_id_full) if need_id_main not in needs or ( - need_id_main in needs and need_id_part and need_id_part not in needs[need_id_main]["parts"] + need_id_main in needs + and need_id_part + and need_id_part not in needs[need_id_main]["parts"] ): need["has_dead_links"] = True if not link_type.get("allow_dead_links", False): @@ -473,7 +504,9 @@ def check_links(needs: dict[str, NeedsInfoType], config: NeedsSphinxConfig) -> N ) -def create_back_links(needs: dict[str, NeedsInfoType], config: NeedsSphinxConfig) -> None: +def create_back_links( + needs: dict[str, NeedsInfoType], config: NeedsSphinxConfig +) -> None: """Create back-links in all found needs. These are fields for each link type, ``_back``, @@ -484,7 +517,9 @@ def create_back_links(needs: dict[str, NeedsInfoType], config: NeedsSphinxConfig option_back = f"{option}_back" for key, need in needs.items(): - need_link_value: list[str] = [need[option]] if isinstance(need[option], str) else need[option] # type: ignore[literal-required] + need_link_value: list[str] = ( + [need[option]] if isinstance(need[option], str) else need[option] # type: ignore[literal-required] + ) for need_id_full in need_link_value: need_id_main, need_id_part = split_need_id(need_id_full) @@ -494,9 +529,14 @@ def create_back_links(needs: dict[str, NeedsInfoType], config: NeedsSphinxConfig # Handling of links to need_parts inside a need if need_id_part and need_id_part in needs[need_id_main]["parts"]: - if option_back not in needs[need_id_main]["parts"][need_id_part].keys(): + if ( + option_back + not in needs[need_id_main]["parts"][need_id_part].keys() + ): needs[need_id_main]["parts"][need_id_part][option_back] = [] # type: ignore[literal-required] - needs[need_id_main]["parts"][need_id_part][option_back].append(key) # type: ignore[literal-required] + needs[need_id_main]["parts"][need_id_part][option_back].append( # type: ignore[literal-required] + key + ) def _fix_list_dyn_func(list: list[str]) -> list[str]: diff --git a/sphinx_needs/directives/needbar.py b/sphinx_needs/directives/needbar.py index 623bef414..598b425a8 100644 --- a/sphinx_needs/directives/needbar.py +++ b/sphinx_needs/directives/needbar.py @@ -82,7 +82,11 @@ def run(self) -> Sequence[nodes.Node]: style = self.options.get("style") matplotlib = import_matplotlib() - style = style.strip() if style else (matplotlib.style.use("default") if matplotlib else "default") + style = ( + style.strip() + if style + else (matplotlib.style.use("default") if matplotlib else "default") + ) legend = "legend" in self.options @@ -167,7 +171,12 @@ def run(self) -> Sequence[nodes.Node]: # 8. create figure # 9. final storage # 10. cleanup matplotlib -def process_needbar(app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element]) -> None: +def process_needbar( + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], +) -> None: env = app.env needs_data = SphinxNeedsData(env) needs_config = NeedsSphinxConfig(env.config) @@ -221,13 +230,19 @@ def process_needbar(app: Sphinx, doctree: nodes.document, fromdocname: str, foun else: # We can only process content with the same lenght for each line if test_columns_length != len(row_data): - raise Exception(f"{error_id}: each content line must have the same length") + raise Exception( + f"{error_id}: each content line must have the same length" + ) # 3. process the labels (maybe from content) xlabels = current_needbar["xlabels"] - xlabels_in_content = bool(xlabels and len(xlabels) >= 1 and xlabels[0] == "FROM_DATA") + xlabels_in_content = bool( + xlabels and len(xlabels) >= 1 and xlabels[0] == "FROM_DATA" + ) ylabels = current_needbar["ylabels"] - ylabels_in_content = bool(ylabels and len(ylabels) >= 1 and ylabels[0] == "FROM_DATA") + ylabels_in_content = bool( + ylabels and len(ylabels) >= 1 and ylabels[0] == "FROM_DATA" + ) if xlabels_in_content: # get xlabels from content => first row in content @@ -265,14 +280,19 @@ def process_needbar(app: Sphinx, doctree: nodes.document, fromdocname: str, foun # 4. transpose the data if needed if current_needbar["transpose"]: - local_data = [[local_data[j][i] for j in range(len(local_data))] for i in range(len(local_data[0]))] + local_data = [ + [local_data[j][i] for j in range(len(local_data))] + for i in range(len(local_data[0])) + ] tmp = ylabels ylabels = xlabels xlabels = tmp # 5. process content local_data_number = [] - need_list = list(prepare_need_list(needs_data.get_or_create_needs().values())) # adds parts to need_list + need_list = list( + prepare_need_list(needs_data.get_or_create_needs().values()) + ) # adds parts to need_list for line in local_data: line_number = [] @@ -335,7 +355,9 @@ def process_needbar(app: Sphinx, doctree: nodes.document, fromdocname: str, foun colors = colors + matplotlib.rcParams["axes.prop_cycle"].by_key()["color"] multi = math.ceil(len(local_data) / len(colors)) if multi > 1: - print(f"{error_id} warning: color schema is smaller than data, double coloring is occurring") + print( + f"{error_id} warning: color schema is smaller than data, double coloring is occurring" + ) colors = colors * multi colors = colors[: len(local_data)] @@ -368,9 +390,13 @@ def process_needbar(app: Sphinx, doctree: nodes.document, fromdocname: str, foun if current_needbar["show_sum"]: try: - bar_label = axes.bar_label(bar, label_type="center") # show label in the middel of each bar + bar_label = axes.bar_label( + bar, label_type="center" + ) # show label in the middel of each bar bar_labels.append(bar_label) - except AttributeError: # bar_label is not support in older matplotlib versions + except ( + AttributeError + ): # bar_label is not support in older matplotlib versions current_needbar["show_sum"] = None current_needbar["show_top_sum"] = None @@ -381,18 +407,24 @@ def process_needbar(app: Sphinx, doctree: nodes.document, fromdocname: str, foun try: bar_label = axes.bar_label(bar) bar_labels.append(bar_label) - except AttributeError: # bar_label is not support in older matplotlib versions + except ( + AttributeError + ): # bar_label is not support in older matplotlib versions current_needbar["show_sum"] = None current_needbar["show_top_sum"] = None sum_rotation = current_needbar["sum_rotation"] - if sum_rotation and (current_needbar["show_top_sum"] or current_needbar["show_sum"]): + if sum_rotation and ( + current_needbar["show_top_sum"] or current_needbar["show_sum"] + ): sum_rotation = sum_rotation.strip() # Rotate the bar labels if sum_rotation.isdigit(): matplotlib.pyplot.setp(bar_labels, rotation=int(sum_rotation)) - centers = [(i + j) / 2.0 for i, j in zip(index[0], index[len(local_data_number) - 1])] + centers = [ + (i + j) / 2.0 for i, j in zip(index[0], index[len(local_data_number) - 1]) + ] if not current_needbar["horizontal"]: # We want to support even older version of matplotlib, which do not support axes.set_xticks(labels) axes.set_xticks(centers) @@ -408,14 +440,18 @@ def process_needbar(app: Sphinx, doctree: nodes.document, fromdocname: str, foun xlabels_rotation = xlabels_rotation.strip() # Rotate the tick labels if xlabels_rotation.isdigit(): - matplotlib.pyplot.setp(axes.get_xticklabels(), rotation=int(xlabels_rotation)) + matplotlib.pyplot.setp( + axes.get_xticklabels(), rotation=int(xlabels_rotation) + ) ylabels_rotation = current_needbar["ylabels_rotation"] if ylabels_rotation: ylabels_rotation = ylabels_rotation.strip() # Rotate the tick labels if ylabels_rotation.isdigit(): - matplotlib.pyplot.setp(axes.get_yticklabels(), rotation=int(ylabels_rotation)) + matplotlib.pyplot.setp( + axes.get_yticklabels(), rotation=int(ylabels_rotation) + ) if current_needbar["title"]: axes.set_title(current_needbar["title"].strip()) @@ -433,7 +469,9 @@ def process_needbar(app: Sphinx, doctree: nodes.document, fromdocname: str, foun # We need to calculate an unique bar-image file name hash_value = hashlib.sha256(id.encode()).hexdigest()[:5] - image_node = save_matplotlib_figure(app, figure, f"need_bar_{hash_value}", fromdocname) + image_node = save_matplotlib_figure( + app, figure, f"need_bar_{hash_value}", fromdocname + ) # Add lineno to node image_node.line = current_needbar["lineno"] diff --git a/sphinx_needs/directives/needextend.py b/sphinx_needs/directives/needextend.py index 886aaa123..054d97f53 100644 --- a/sphinx_needs/directives/needextend.py +++ b/sphinx_needs/directives/needextend.py @@ -44,9 +44,13 @@ def run(self) -> Sequence[nodes.Node]: extend_filter = self.arguments[0] if self.arguments else None if not extend_filter: - raise NeedsInvalidFilter(f"Filter of needextend must be set. See {env.docname}:{self.lineno}") + raise NeedsInvalidFilter( + f"Filter of needextend must be set. See {env.docname}:{self.lineno}" + ) - strict_option = self.options.get("strict", str(NeedsSphinxConfig(self.env.app.config).needextend_strict)) + strict_option = self.options.get( + "strict", str(NeedsSphinxConfig(self.env.app.config).needextend_strict) + ) strict = True if strict_option.upper() == "TRUE": strict = True @@ -69,7 +73,9 @@ def run(self) -> Sequence[nodes.Node]: def extend_needs_data( - all_needs: dict[str, NeedsInfoType], extends: dict[str, NeedsExtendType], needs_config: NeedsSphinxConfig + all_needs: dict[str, NeedsInfoType], + extends: dict[str, NeedsExtendType], + needs_config: NeedsSphinxConfig, ) -> None: """Use data gathered from needextend directives to modify fields of existing needs.""" @@ -81,7 +87,9 @@ def extend_needs_data( if need_filter in all_needs: # a single known ID found_needs = [all_needs[need_filter]] - elif need_filter is not None and re.fullmatch(needs_config.id_regex, need_filter): + elif need_filter is not None and re.fullmatch( + needs_config.id_regex, need_filter + ): # an unknown ID error = f"Provided id {need_filter} for needextend does not exist." if current_needextend["strict"]: @@ -92,7 +100,9 @@ def extend_needs_data( else: # a filter string try: - found_needs = filter_needs(all_needs.values(), needs_config, need_filter) + found_needs = filter_needs( + all_needs.values(), needs_config, need_filter + ) except NeedsInvalidFilter as e: raise NeedsInvalidFilter( f"Filter not valid for needextend on page {current_needextend['docname']}:\n{e}" @@ -108,7 +118,9 @@ def extend_needs_data( if option.startswith("+"): option_name = option[1:] if option_name in link_names: - if value.strip().startswith("[[") and value.strip().endswith("]]"): # dynamic function + if value.strip().startswith("[[") and value.strip().endswith( + "]]" + ): # dynamic function need[option_name].append(value) else: for ref_need in [i.strip() for i in re.split(";|,", value)]: @@ -116,13 +128,18 @@ def extend_needs_data( logger.warning( f"Provided link id {ref_need} for needextend does not exist. [needs]", type="needs", - location=(current_needextend["docname"], current_needextend["lineno"]), + location=( + current_needextend["docname"], + current_needextend["lineno"], + ), ) continue if ref_need not in need[option_name]: need[option_name].append(ref_need) elif option_name in list_values: - if value.strip().startswith("[[") and value.strip().endswith("]]"): # dynamic function + if value.strip().startswith("[[") and value.strip().endswith( + "]]" + ): # dynamic function need[option_name].append(value) else: for item in [i.strip() for i in re.split(";|,", value)]: @@ -145,7 +162,9 @@ def extend_needs_data( else: if option in link_names: need[option] = [] - if value.strip().startswith("[[") and value.strip().endswith("]]"): # dynamic function + if value.strip().startswith("[[") and value.strip().endswith( + "]]" + ): # dynamic function need[option].append(value) else: for ref_need in [i.strip() for i in re.split(";|,", value)]: @@ -153,12 +172,17 @@ def extend_needs_data( logger.warning( f"Provided link id {ref_need} for needextend does not exist. [needs]", type="needs", - location=(current_needextend["docname"], current_needextend["lineno"]), + location=( + current_needextend["docname"], + current_needextend["lineno"], + ), ) continue need[option].append(ref_need) elif option in list_values: - if value.strip().startswith("[[") and value.strip().endswith("]]"): # dynamic function + if value.strip().startswith("[[") and value.strip().endswith( + "]]" + ): # dynamic function need[option].append(value) else: need[option] = [i.strip() for i in re.split(";|,", value)] diff --git a/sphinx_needs/directives/needextract.py b/sphinx_needs/directives/needextract.py index 18f5cb060..9ceba1a09 100644 --- a/sphinx_needs/directives/needextract.py +++ b/sphinx_needs/directives/needextract.py @@ -43,7 +43,9 @@ class NeedextractDirective(FilterBase): def run(self) -> Sequence[nodes.Node]: env = self.env - targetid = "needextract-{docname}-{id}".format(docname=env.docname, id=env.new_serialno("needextract")) + targetid = "needextract-{docname}-{id}".format( + docname=env.docname, id=env.new_serialno("needextract") + ) targetnode = nodes.target("", "", ids=[targetid]) filter_arg = self.arguments[0] if self.arguments else None @@ -67,7 +69,10 @@ def run(self) -> Sequence[nodes.Node]: def process_needextract( - app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element] + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], ) -> None: """ Replace all needextract nodes with a list of the collected needs. @@ -88,14 +93,18 @@ def process_needextract( # check if filter argument and option filter both exist need_filter_arg = current_needextract["filter_arg"] if need_filter_arg and current_needextract["filter"]: - raise NeedsInvalidFilter("Needextract can't have filter arguments and option filter at the same time.") + raise NeedsInvalidFilter( + "Needextract can't have filter arguments and option filter at the same time." + ) elif need_filter_arg: # check if given filter argument is need-id if need_filter_arg in all_needs: need_filter_arg = f'id == "{need_filter_arg}"' elif re.fullmatch(needs_config.id_regex, need_filter_arg): # check if given filter argument is need-id, but not exists - raise NeedsInvalidFilter(f"Provided id {need_filter_arg} for needextract does not exist.") + raise NeedsInvalidFilter( + f"Provided id {need_filter_arg} for needextract does not exist." + ) current_needextract["filter"] = need_filter_arg found_needs = process_filters(app, all_needs.values(), current_needextract) @@ -118,7 +127,9 @@ def process_needextract( content.append(need_extract) if len(content) == 0: - content.append(no_needs_found_paragraph(current_needextract.get("filter_warning"))) + content.append( + no_needs_found_paragraph(current_needextract.get("filter_warning")) + ) if current_needextract["show_filters"]: content.append(used_filter_paragraph(current_needextract)) diff --git a/sphinx_needs/directives/needfilter.py b/sphinx_needs/directives/needfilter.py index ef0cb3d71..0d7cd00c8 100644 --- a/sphinx_needs/directives/needfilter.py +++ b/sphinx_needs/directives/needfilter.py @@ -49,7 +49,9 @@ def layout(argument: str) -> str: def run(self) -> Sequence[nodes.Node]: env = self.env - targetid = "needfilter-{docname}-{id}".format(docname=env.docname, id=env.new_serialno("needfilter")) + targetid = "needfilter-{docname}-{id}".format( + docname=env.docname, id=env.new_serialno("needfilter") + ) targetnode = nodes.target("", "", ids=[targetid]) # Add the need and all needed information @@ -72,7 +74,10 @@ def run(self) -> Sequence[nodes.Node]: def process_needfilters( - app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element] + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], ) -> None: # Replace all needlist nodes with a list of the collected needs. # Augment each need with a backlink to the original location. @@ -129,7 +134,14 @@ def process_needfilters( status_colspec = nodes.colspec(colwidth=5) links_colspec = nodes.colspec(colwidth=5) tags_colspec = nodes.colspec(colwidth=5) - tgroup += [id_colspec, title_colspec, type_colspec, status_colspec, links_colspec, tags_colspec] + tgroup += [ + id_colspec, + title_colspec, + type_colspec, + status_colspec, + links_colspec, + tags_colspec, + ] tgroup += nodes.thead( "", nodes.row( @@ -170,7 +182,9 @@ def process_needfilters( else: ref = nodes.reference("", "") ref["refdocname"] = need_info["docname"] - ref["refuri"] = builder.get_relative_uri(fromdocname, need_info["docname"]) + ref["refuri"] = builder.get_relative_uri( + fromdocname, need_info["docname"] + ) ref["refuri"] += "#" + target_id ref.append(title) line_node += ref @@ -178,11 +192,17 @@ def process_needfilters( line_block.append(line_node) elif current_needfilter["layout"] == "table": row = nodes.row() - row += row_col_maker(app, fromdocname, all_needs, need_info, "id", make_ref=True) + row += row_col_maker( + app, fromdocname, all_needs, need_info, "id", make_ref=True + ) row += row_col_maker(app, fromdocname, all_needs, need_info, "title") - row += row_col_maker(app, fromdocname, all_needs, need_info, "type_name") + row += row_col_maker( + app, fromdocname, all_needs, need_info, "type_name" + ) row += row_col_maker(app, fromdocname, all_needs, need_info, "status") - row += row_col_maker(app, fromdocname, all_needs, need_info, "links", ref_lookup=True) + row += row_col_maker( + app, fromdocname, all_needs, need_info, "links", ref_lookup=True + ) row += row_col_maker(app, fromdocname, all_needs, need_info, "tags") tbody += row elif current_needfilter["layout"] == "diagram": @@ -203,9 +223,13 @@ def process_needfilters( link = "" diagram_template = Template(needs_config.diagram_template) - node_text = diagram_template.render(**need_info, **needs_config.render_context) + node_text = diagram_template.render( + **need_info, **needs_config.render_context + ) - puml_node["uml"] += '{style} "{node_text}" as {id} [[{link}]] {color}\n'.format( + puml_node[ + "uml" + ] += '{style} "{node_text}" as {id} [[{link}]] {color}\n'.format( id=need_info["id"], node_text=node_text, link=link, @@ -213,7 +237,9 @@ def process_needfilters( style=need_info["type_style"], ) for link in need_info["links"]: - puml_connections += "{id} --> {link}\n".format(id=need_info["id"], link=link) + puml_connections += "{id} --> {link}\n".format( + id=need_info["id"], link=link + ) if current_needfilter["layout"] == "list": content.append(line_block) @@ -227,11 +253,15 @@ def process_needfilters( puml_node["uml"] += create_legend(needs_config.types) puml_node["uml"] += "@enduml" puml_node["incdir"] = os.path.dirname(current_needfilter["docname"]) - puml_node["filename"] = os.path.split(current_needfilter["docname"])[1] # Needed for plantuml >= 0.9 + puml_node["filename"] = os.path.split(current_needfilter["docname"])[ + 1 + ] # Needed for plantuml >= 0.9 content.append(puml_node) if len(content) == 0: - content.append(no_needs_found_paragraph(current_needfilter.get("filter_warning"))) + content.append( + no_needs_found_paragraph(current_needfilter.get("filter_warning")) + ) if current_needfilter["show_filters"]: para_node = nodes.paragraph() filter_text = "Used filter:" @@ -240,17 +270,25 @@ def process_needfilters( if len(current_needfilter["status"]) > 0 else "" ) - if len(current_needfilter["status"]) > 0 and len(current_needfilter["tags"]) > 0: + if ( + len(current_needfilter["status"]) > 0 + and len(current_needfilter["tags"]) > 0 + ): filter_text += " AND " filter_text += ( - " tags(%s)" % " OR ".join(current_needfilter["tags"]) if len(current_needfilter["tags"]) > 0 else "" + " tags(%s)" % " OR ".join(current_needfilter["tags"]) + if len(current_needfilter["tags"]) > 0 + else "" ) - if (len(current_needfilter["status"]) > 0 or len(current_needfilter["tags"]) > 0) and len( - current_needfilter["types"] - ) > 0: + if ( + len(current_needfilter["status"]) > 0 + or len(current_needfilter["tags"]) > 0 + ) and len(current_needfilter["types"]) > 0: filter_text += " AND " filter_text += ( - " types(%s)" % " OR ".join(current_needfilter["types"]) if len(current_needfilter["types"]) > 0 else "" + " types(%s)" % " OR ".join(current_needfilter["types"]) + if len(current_needfilter["types"]) > 0 + else "" ) filter_node = nodes.emphasis(filter_text, filter_text) diff --git a/sphinx_needs/directives/needflow.py b/sphinx_needs/directives/needflow.py index 31572afb4..5f4df8d92 100644 --- a/sphinx_needs/directives/needflow.py +++ b/sphinx_needs/directives/needflow.py @@ -74,7 +74,9 @@ def run(self) -> Sequence[nodes.Node]: targetnode = nodes.target("", "", ids=[targetid]) all_link_types = ",".join(x["option"] for x in needs_config.extra_links) - link_types = split_link_types(self.options.get("link_types", all_link_types), location) + link_types = split_link_types( + self.options.get("link_types", all_link_types), location + ) config_names = self.options.get("config") configs = [] @@ -220,7 +222,12 @@ def walk_curr_need_tree( # check curr need child has children or has parts if curr_child_need["parent_needs_back"] or curr_child_need["parts"]: curr_need_tree += walk_curr_need_tree( - app, fromdocname, current_needflow, all_needs, found_needs, curr_child_need + app, + fromdocname, + current_needflow, + all_needs, + found_needs, + curr_child_need, ) # add newline for next element curr_need_tree += "\n" @@ -261,7 +268,9 @@ def cal_needs_node( top_needs = get_root_needs(found_needs) curr_need_tree = "" for top_need in top_needs: - top_need_node = get_need_node_rep_for_plantuml(app, fromdocname, current_needflow, all_needs, top_need) + top_need_node = get_need_node_rep_for_plantuml( + app, fromdocname, current_needflow, all_needs, top_need + ) curr_need_tree += ( top_need_node + walk_curr_need_tree( @@ -278,7 +287,12 @@ def cal_needs_node( @measure_time("needflow") -def process_needflow(app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element]) -> None: +def process_needflow( + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], +) -> None: # Replace all needflow nodes with a list of the collected needs. # Augment each need with a backlink to the original location. env = app.env @@ -305,7 +319,9 @@ def process_needflow(app: Sphinx, doctree: nodes.document, fromdocname: str, fou if lt not in link_type_names: logger.warning( "Unknown link type {link_type} in needflow {flow}. Allowed values: {link_types} [needs]".format( - link_type=lt, flow=current_needflow["target_id"], link_types=",".join(link_type_names) + link_type=lt, + flow=current_needflow["target_id"], + link_types=",".join(link_type_names), ), type="needs", ) @@ -342,7 +358,9 @@ def process_needflow(app: Sphinx, doctree: nodes.document, fromdocname: str, fou config = current_needflow["config"] if config and len(config) >= 3: # Remove all empty lines - config = "\n".join([line.strip() for line in config.split("\n") if line.strip()]) + config = "\n".join( + [line.strip() for line in config.split("\n") if line.strip()] + ) puml_node["uml"] += "\n' Config\n\n" puml_node["uml"] += config puml_node["uml"] += "\n\n" @@ -353,9 +371,13 @@ def process_needflow(app: Sphinx, doctree: nodes.document, fromdocname: str, fou for link_type in link_types: # Skip link-type handling, if it is not part of a specified list of allowed link_types or # if not part of the overall configuration of needs_flow_link_types - if (current_needflow["link_types"] and link_type["option"].upper() not in option_link_types) or ( + if ( + current_needflow["link_types"] + and link_type["option"].upper() not in option_link_types + ) or ( not current_needflow["link_types"] - and link_type["option"].upper() not in allowed_link_types_options + and link_type["option"].upper() + not in allowed_link_types_options ): continue @@ -367,30 +389,42 @@ def process_needflow(app: Sphinx, doctree: nodes.document, fromdocname: str, fou # If source or target of link is a need_part, a specific style is needed if "." in link or "." in need_info["id_complete"]: final_link = link - if current_needflow["show_link_names"] or needs_config.flow_show_links: + if ( + current_needflow["show_link_names"] + or needs_config.flow_show_links + ): desc = link_type["outgoing"] + "\\n" comment = f": {desc}" else: comment = "" if "style_part" in link_type and link_type["style_part"]: - link_style = "[{style}]".format(style=link_type["style_part"]) + link_style = "[{style}]".format( + style=link_type["style_part"] + ) else: link_style = "[dotted]" else: final_link = link - if current_needflow["show_link_names"] or needs_config.flow_show_links: + if ( + current_needflow["show_link_names"] + or needs_config.flow_show_links + ): comment = ": {desc}".format(desc=link_type["outgoing"]) else: comment = "" if "style" in link_type and link_type["style"]: - link_style = "[{style}]".format(style=link_type["style"]) + link_style = "[{style}]".format( + style=link_type["style"] + ) else: link_style = "" # Do not create an links, if the link target is not part of the search result. - if final_link not in [x["id"] for x in found_needs if x["is_need"]] and final_link not in [ + if final_link not in [ + x["id"] for x in found_needs if x["is_need"] + ] and final_link not in [ x["id_complete"] for x in found_needs if x["is_part"] ]: continue @@ -415,7 +449,9 @@ def process_needflow(app: Sphinx, doctree: nodes.document, fromdocname: str, fou ) # calculate needs node representation for plantuml - puml_node["uml"] += cal_needs_node(app, fromdocname, current_needflow, all_needs.values(), found_needs) + puml_node["uml"] += cal_needs_node( + app, fromdocname, current_needflow, all_needs.values(), found_needs + ) puml_node["uml"] += "\n' Connection definition \n\n" puml_node["uml"] += puml_connections @@ -426,7 +462,9 @@ def process_needflow(app: Sphinx, doctree: nodes.document, fromdocname: str, fou puml_node["uml"] += "\n@enduml" puml_node["incdir"] = os.path.dirname(current_needflow["docname"]) - puml_node["filename"] = os.path.split(current_needflow["docname"])[1] # Needed for plantuml >= 0.9 + puml_node["filename"] = os.path.split(current_needflow["docname"])[ + 1 + ] # Needed for plantuml >= 0.9 scale = int(current_needflow["scale"]) # if scale != 100: @@ -452,8 +490,14 @@ def process_needflow(app: Sphinx, doctree: nodes.document, fromdocname: str, fou gen_flow_link = generate_name(app, puml_node.children[0], file_ext) current_file_parts = fromdocname.split("/") subfolder_amount = len(current_file_parts) - 1 - img_locaton = "../" * subfolder_amount + "_images/" + gen_flow_link[0].split("/")[-1] - flow_ref = nodes.reference("t", current_needflow["caption"], refuri=img_locaton) + img_locaton = ( + "../" * subfolder_amount + + "_images/" + + gen_flow_link[0].split("/")[-1] + ) + flow_ref = nodes.reference( + "t", current_needflow["caption"], refuri=img_locaton + ) puml_node += nodes.caption("", "", flow_ref) # Add lineno to node @@ -461,25 +505,36 @@ def process_needflow(app: Sphinx, doctree: nodes.document, fromdocname: str, fou content.append(puml_node) else: # no needs found - content.append(no_needs_found_paragraph(current_needflow.get("filter_warning"))) + content.append( + no_needs_found_paragraph(current_needflow.get("filter_warning")) + ) if current_needflow["show_filters"]: para = nodes.paragraph() filter_text = "Used filter:" filter_text += ( - " status(%s)" % " OR ".join(current_needflow["status"]) if len(current_needflow["status"]) > 0 else "" + " status(%s)" % " OR ".join(current_needflow["status"]) + if len(current_needflow["status"]) > 0 + else "" ) - if len(current_needflow["status"]) > 0 and len(current_needflow["tags"]) > 0: + if ( + len(current_needflow["status"]) > 0 + and len(current_needflow["tags"]) > 0 + ): filter_text += " AND " filter_text += ( - " tags(%s)" % " OR ".join(current_needflow["tags"]) if len(current_needflow["tags"]) > 0 else "" + " tags(%s)" % " OR ".join(current_needflow["tags"]) + if len(current_needflow["tags"]) > 0 + else "" ) - if (len(current_needflow["status"]) > 0 or len(current_needflow["tags"]) > 0) and len( - current_needflow["types"] - ) > 0: + if ( + len(current_needflow["status"]) > 0 or len(current_needflow["tags"]) > 0 + ) and len(current_needflow["types"]) > 0: filter_text += " AND " filter_text += ( - " types(%s)" % " OR ".join(current_needflow["types"]) if len(current_needflow["types"]) > 0 else "" + " types(%s)" % " OR ".join(current_needflow["types"]) + if len(current_needflow["types"]) > 0 + else "" ) filter_node = nodes.emphasis(filter_text, filter_text) diff --git a/sphinx_needs/directives/needgantt.py b/sphinx_needs/directives/needgantt.py index d0f4b9c11..5f8e8f3f1 100644 --- a/sphinx_needs/directives/needgantt.py +++ b/sphinx_needs/directives/needgantt.py @@ -88,15 +88,21 @@ def run(self) -> Sequence[nodes.Node]: timeline_options = ["daily", "weekly", "monthly"] if timeline and timeline not in timeline_options: raise NeedGanttException( - "Given scale value {} is invalid. Please use: " "{}".format(timeline, ",".join(timeline_options)) + "Given scale value {} is invalid. Please use: " "{}".format( + timeline, ",".join(timeline_options) + ) ) else: timeline = None # Timeline/scale not set later no_color = "no_color" in self.options - duration_option = self.options.get("duration_option", needs_config.duration_option) - completion_option = self.options.get("completion_option", needs_config.completion_option) + duration_option = self.options.get( + "duration_option", needs_config.duration_option + ) + completion_option = self.options.get( + "completion_option", needs_config.completion_option + ) # Add the needgantt and all needed information SphinxNeedsData(env).get_or_create_gantts()[targetid] = { @@ -121,7 +127,9 @@ def run(self) -> Sequence[nodes.Node]: return [targetnode] + [Needgantt("")] def get_link_type_option(self, name: str, default: str = "") -> list[str]: - link_types = [x.strip() for x in re.split(";|,", self.options.get(name, default))] + link_types = [ + x.strip() for x in re.split(";|,", self.options.get(name, default)) + ] conf_link_types = NeedsSphinxConfig(self.env.config).extra_links conf_link_types_name = [x["option"] for x in conf_link_types] @@ -131,14 +139,20 @@ def get_link_type_option(self, name: str, default: str = "") -> list[str]: continue if link_type not in conf_link_types_name: raise SphinxNeedsLinkTypeException( - link_type + "does not exist in configuration option needs_extra_links" + link_type + + "does not exist in configuration option needs_extra_links" ) final_link_types.append(link_type) return final_link_types -def process_needgantt(app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element]) -> None: +def process_needgantt( + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], +) -> None: # Replace all needgantt nodes with a list of the collected needs. env = app.env needs_config = NeedsSphinxConfig(app.config) @@ -196,7 +210,9 @@ def process_needgantt(app: Sphinx, doctree: nodes.document, fromdocname: str, fo except Exception: raise NeedGanttException( 'start_date "{}"for needgantt is invalid. ' - 'File: {}:current_needgantt["lineno"]'.format(start_date_string, current_needgantt["docname"]) + 'File: {}:current_needgantt["lineno"]'.format( + start_date_string, current_needgantt["docname"] + ) ) month = MONTH_NAMES[int(start_date.strftime("%m"))] @@ -212,12 +228,16 @@ def process_needgantt(app: Sphinx, doctree: nodes.document, fromdocname: str, fo complete = None if current_needgantt["milestone_filter"]: - is_milestone = filter_single_need(need, needs_config, current_needgantt["milestone_filter"]) + is_milestone = filter_single_need( + need, needs_config, current_needgantt["milestone_filter"] + ) else: is_milestone = False if current_needgantt["milestone_filter"] and is_milestone: - gantt_element = "[{}] as [{}] lasts 0 days\n".format(need["title"], need["id"]) + gantt_element = "[{}] as [{}] lasts 0 days\n".format( + need["title"], need["id"] + ) else: # Normal gantt element handling duration_option = current_needgantt["duration_option"] duration = need[duration_option] # type: ignore[literal-required] @@ -230,18 +250,26 @@ def process_needgantt(app: Sphinx, doctree: nodes.document, fromdocname: str, fo type="needs", ) duration = 1 - gantt_element = "[{}] as [{}] lasts {} days\n".format(need["title"], need["id"], duration) + gantt_element = "[{}] as [{}] lasts {} days\n".format( + need["title"], need["id"], duration + ) if complete: complete = complete.replace("%", "") - el_completion_string += "[{}] is {}% completed\n".format(need["title"], complete) + el_completion_string += "[{}] is {}% completed\n".format( + need["title"], complete + ) - el_color_string += "[{}] is colored in {}\n".format(need["title"], need["type_color"]) + el_color_string += "[{}] is colored in {}\n".format( + need["title"], need["type_color"] + ) puml_node["uml"] += gantt_element puml_node["uml"] += "\n' Element links definition \n\n" - puml_node["uml"] += "\n' Deactivated, as currently supported by plantuml beta only" + puml_node[ + "uml" + ] += "\n' Deactivated, as currently supported by plantuml beta only" puml_node["uml"] += "\n' Element completion definition \n\n" puml_node["uml"] += el_completion_string + "\n" @@ -257,10 +285,16 @@ def process_needgantt(app: Sphinx, doctree: nodes.document, fromdocname: str, fo puml_node["uml"] += "\n' Constraints definition \n\n" for need in found_needs: if current_needgantt["milestone_filter"]: - is_milestone = filter_single_need(need, needs_config, current_needgantt["milestone_filter"]) + is_milestone = filter_single_need( + need, needs_config, current_needgantt["milestone_filter"] + ) else: is_milestone = False - for con_type in ("starts_with_links", "starts_after_links", "ends_with_links"): + for con_type in ( + "starts_with_links", + "starts_after_links", + "ends_with_links", + ): if is_milestone: keyword = "happens" elif con_type in ["starts_with_links", "starts_after_links"]: @@ -288,7 +322,9 @@ def process_needgantt(app: Sphinx, doctree: nodes.document, fromdocname: str, fo puml_node["uml"] += "\n@endgantt" puml_node["incdir"] = os.path.dirname(current_needgantt["docname"]) - puml_node["filename"] = os.path.split(current_needgantt["docname"])[1] # Needed for plantuml >= 0.9 + puml_node["filename"] = os.path.split(current_needgantt["docname"])[ + 1 + ] # Needed for plantuml >= 0.9 scale = int(current_needgantt["scale"]) # if scale != 100: @@ -311,14 +347,20 @@ def process_needgantt(app: Sphinx, doctree: nodes.document, fromdocname: str, fo gen_flow_link = generate_name(app, puml_node.children[0], file_ext) current_file_parts = fromdocname.split("/") subfolder_amount = len(current_file_parts) - 1 - img_location = "../" * subfolder_amount + "_images/" + gen_flow_link[0].split("/")[-1] - flow_ref = nodes.reference("t", current_needgantt["caption"], refuri=img_location) + img_location = ( + "../" * subfolder_amount + "_images/" + gen_flow_link[0].split("/")[-1] + ) + flow_ref = nodes.reference( + "t", current_needgantt["caption"], refuri=img_location + ) puml_node += nodes.caption("", "", flow_ref) content.append(puml_node) if len(found_needs) == 0: - content = [no_needs_found_paragraph(current_needgantt.get("filter_warning"))] + content = [ + no_needs_found_paragraph(current_needgantt.get("filter_warning")) + ] if current_needgantt["show_filters"]: content.append(get_filter_para(current_needgantt)) diff --git a/sphinx_needs/directives/needimport.py b/sphinx_needs/directives/needimport.py index b66148079..cf9d26cc3 100644 --- a/sphinx_needs/directives/needimport.py +++ b/sphinx_needs/directives/needimport.py @@ -73,19 +73,25 @@ def run(self) -> Sequence[nodes.Node]: response.json() ) # The downloaded file MUST be json. Everything else we do not handle! except Exception as e: - raise NeedimportException(f"Getting {need_import_path} didn't work. Reason: {e}.") + raise NeedimportException( + f"Getting {need_import_path} didn't work. Reason: {e}." + ) else: logger.info(f"Importing needs from {need_import_path}") if not os.path.isabs(need_import_path): # Relative path should start from current rst file directory curr_dir = os.path.dirname(self.docname) - new_need_import_path = os.path.join(self.env.app.srcdir, curr_dir, need_import_path) + new_need_import_path = os.path.join( + self.env.app.srcdir, curr_dir, need_import_path + ) correct_need_import_path = new_need_import_path if not os.path.exists(new_need_import_path): # Check the old way that calculates relative path starting from conf.py directory - old_need_import_path = os.path.join(self.env.app.srcdir, need_import_path) + old_need_import_path = os.path.join( + self.env.app.srcdir, need_import_path + ) if os.path.exists(old_need_import_path): correct_need_import_path = old_need_import_path logger.warning( @@ -97,14 +103,20 @@ def run(self) -> Sequence[nodes.Node]: ) else: # Absolute path starts with /, based on the source directory. The / need to be striped - correct_need_import_path = os.path.join(self.env.app.srcdir, need_import_path[1:]) + correct_need_import_path = os.path.join( + self.env.app.srcdir, need_import_path[1:] + ) if not os.path.exists(correct_need_import_path): - raise ReferenceError(f"Could not load needs import file {correct_need_import_path}") + raise ReferenceError( + f"Could not load needs import file {correct_need_import_path}" + ) errors = check_needs_file(correct_need_import_path) if errors.schema: - logger.info(f"Schema validation errors detected in file {correct_need_import_path}:") + logger.info( + f"Schema validation errors detected in file {correct_need_import_path}:" + ) for error in errors.schema: logger.info(f' {error.message} -> {".".join(error.path)}') @@ -121,13 +133,19 @@ def run(self) -> Sequence[nodes.Node]: if not isinstance(version, str): raise KeyError except KeyError: - raise CorruptedNeedsFile(f"Key 'current_version' missing or corrupted in {correct_need_import_path}") + raise CorruptedNeedsFile( + f"Key 'current_version' missing or corrupted in {correct_need_import_path}" + ) if version not in needs_import_list["versions"].keys(): - raise VersionNotFound(f"Version {version} not found in needs import file {correct_need_import_path}") + raise VersionNotFound( + f"Version {version} not found in needs import file {correct_need_import_path}" + ) needs_config = NeedsSphinxConfig(self.config) # TODO this is not exactly NeedsInfoType, because the export removes/adds some keys - needs_list: dict[str, NeedsInfoType] = needs_import_list["versions"][version]["needs"] + needs_list: dict[str, NeedsInfoType] = needs_import_list["versions"][version][ + "needs" + ] # Filter imported needs needs_list_filtered = {} @@ -161,13 +179,20 @@ def run(self) -> Sequence[nodes.Node]: for id in needs_list: # Manipulate links in all link types for extra_link in extra_links: - if extra_link["option"] in need and id in need[extra_link["option"]]: # type: ignore[literal-required] + if ( + extra_link["option"] in need + and id in need[extra_link["option"]] # type: ignore[literal-required] + ): for n, link in enumerate(need[extra_link["option"]]): # type: ignore[literal-required] if id == link: - need[extra_link["option"]][n] = "".join([id_prefix, id]) # type: ignore[literal-required] + need[extra_link["option"]][n] = "".join( # type: ignore[literal-required] + [id_prefix, id] + ) # Manipulate descriptions # ToDo: Use regex for better matches. - need["description"] = need["description"].replace(id, "".join([id_prefix, id])) # type: ignore[typeddict-item] + need["description"] = need["description"].replace( # type: ignore[typeddict-item] + id, "".join([id_prefix, id]) + ) # tags update for need in needs_list.values(): @@ -194,8 +219,12 @@ def run(self) -> Sequence[nodes.Node]: for need in needs_list.values(): # Set some values based on given option or value from imported need. need["template"] = self.options.get("template", need.get("template")) - need["pre_template"] = self.options.get("pre_template", need.get("pre_template")) - need["post_template"] = self.options.get("post_template", need.get("post_template")) + need["pre_template"] = self.options.get( + "pre_template", need.get("pre_template") + ) + need["post_template"] = self.options.get( + "post_template", need.get("post_template") + ) need["layout"] = self.options.get("layout", need.get("layout")) need["style"] = self.options.get("style", need.get("style")) diff --git a/sphinx_needs/directives/needlist.py b/sphinx_needs/directives/needlist.py index 91a2950f2..d6b1a528d 100644 --- a/sphinx_needs/directives/needlist.py +++ b/sphinx_needs/directives/needlist.py @@ -41,7 +41,9 @@ class NeedlistDirective(FilterBase): def run(self) -> Sequence[nodes.Node]: env = self.env - targetid = "needlist-{docname}-{id}".format(docname=env.docname, id=env.new_serialno("needlist")) + targetid = "needlist-{docname}-{id}".format( + docname=env.docname, id=env.new_serialno("needlist") + ) targetnode = nodes.target("", "", ids=[targetid]) # Add the need and all needed information @@ -60,7 +62,12 @@ def run(self) -> Sequence[nodes.Node]: return [targetnode, Needlist("")] -def process_needlist(app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element]) -> None: +def process_needlist( + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], +) -> None: """ Replace all needlist nodes with a list of the collected needs. Augment each need with a backlink to the original location. @@ -81,7 +88,7 @@ def process_needlist(app: Sphinx, doctree: nodes.document, fromdocname: str, fou all_needs = list(SphinxNeedsData(env).get_or_create_needs().values()) found_needs = process_filters(app, all_needs, current_needfilter) - if 0 < len(found_needs): + if len(found_needs) > 0: line_block = nodes.line_block() # Add lineno to node @@ -102,10 +109,14 @@ def process_needlist(app: Sphinx, doctree: nodes.document, fromdocname: str, fou if need_info["hide"]: para += title elif need_info["is_external"]: - assert need_info["external_url"] is not None, "External need without URL" + assert ( + need_info["external_url"] is not None + ), "External need without URL" ref = nodes.reference("", "") - ref["refuri"] = check_and_calc_base_url_rel_path(need_info["external_url"], fromdocname) + ref["refuri"] = check_and_calc_base_url_rel_path( + need_info["external_url"], fromdocname + ) ref["classes"].append(need_info["external_css"]) ref.append(title) @@ -114,7 +125,9 @@ def process_needlist(app: Sphinx, doctree: nodes.document, fromdocname: str, fou target_id = need_info["target_id"] ref = nodes.reference("", "") ref["refdocname"] = need_info["docname"] - ref["refuri"] = builder.get_relative_uri(fromdocname, need_info["docname"]) + ref["refuri"] = builder.get_relative_uri( + fromdocname, need_info["docname"] + ) ref["refuri"] += "#" + target_id ref.append(title) para += ref @@ -122,7 +135,9 @@ def process_needlist(app: Sphinx, doctree: nodes.document, fromdocname: str, fou content.append(line_block) if len(content) == 0: - content.append(no_needs_found_paragraph(current_needfilter.get("filter_warning"))) + content.append( + no_needs_found_paragraph(current_needfilter.get("filter_warning")) + ) if current_needfilter["show_filters"]: content.append(used_filter_paragraph(current_needfilter)) diff --git a/sphinx_needs/directives/needpie.py b/sphinx_needs/directives/needpie.py index f055dffe3..700c25247 100644 --- a/sphinx_needs/directives/needpie.py +++ b/sphinx_needs/directives/needpie.py @@ -106,7 +106,12 @@ def run(self) -> Sequence[nodes.Node]: @measure_time("needpie") -def process_needpie(app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element]) -> None: +def process_needpie( + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], +) -> None: env = app.env needs_data = SphinxNeedsData(env) needs_config = NeedsSphinxConfig(env.config) @@ -149,7 +154,9 @@ def process_needpie(app: Sphinx, doctree: nodes.document, fromdocname: str, foun content = current_needpie["content"] sizes = [] - need_list = list(prepare_need_list(needs_data.get_or_create_needs().values())) # adds parts to need_list + need_list = list( + prepare_need_list(needs_data.get_or_create_needs().values()) + ) # adds parts to need_list if content and not current_needpie["filter_func"]: for line in content: if line.isdigit(): @@ -160,7 +167,9 @@ def process_needpie(app: Sphinx, doctree: nodes.document, fromdocname: str, foun elif current_needpie["filter_func"] and not content: try: # check and get filter_func - filter_func, filter_args = check_and_get_external_filter_func(current_needpie.get("filter_func")) + filter_func, filter_args = check_and_get_external_filter_func( + current_needpie.get("filter_func") + ) # execute filter_func code # Provides only a copy of needs to avoid data manipulations. context = { @@ -192,7 +201,9 @@ def process_needpie(app: Sphinx, doctree: nodes.document, fromdocname: str, foun except Exception as e: raise e elif current_needpie["filter_func"] and content: - logger.error("filter_func and content can't be used at the same time for needpie.") + logger.error( + "filter_func and content can't be used at the same time for needpie." + ) else: logger.error("Both filter_func and content are not used for needpie.") @@ -215,7 +226,9 @@ def process_needpie(app: Sphinx, doctree: nodes.document, fromdocname: str, foun shadow = current_needpie["shadow"] text_color = current_needpie["text_color"] - fig, axes = matplotlib.pyplot.subplots(figsize=(8, 4), subplot_kw={"aspect": "equal"}) + fig, axes = matplotlib.pyplot.subplots( + figsize=(8, 4), subplot_kw={"aspect": "equal"} + ) pie_kwargs = { "labels": labels, @@ -229,7 +242,9 @@ def process_needpie(app: Sphinx, doctree: nodes.document, fromdocname: str, foun if text_color: pie_kwargs["textprops"] = {"color": text_color} - wedges, _texts, autotexts = axes.pie(sizes, normalize=sum(float(s) for s in sizes) >= 1, **pie_kwargs) + wedges, _texts, autotexts = axes.pie( + sizes, normalize=sum(float(s) for s in sizes) >= 1, **pie_kwargs + ) ratio = 20 # we will remove all labels with size smaller 5% legend_enforced = False @@ -248,12 +263,12 @@ def process_needpie(app: Sphinx, doctree: nodes.document, fromdocname: str, foun for i in range(len(sizes)): if sum(sizes) > 0: labels[i] = "{label} {percent:.1f}% ({size:.0f})".format( - label=labels[i], percent=100 * sizes[i] / sum(sizes), size=sizes[i] + label=labels[i], + percent=100 * sizes[i] / sum(sizes), + size=sizes[i], ) else: - labels[i] = "{label} {percent:.1f}% ({size:.0f})".format( - label=labels[i], percent=0.0, size=sizes[i] - ) + labels[i] = f"{labels[i]} {0.0:.1f}% ({sizes[i]:.0f})" if text_color: for autotext in autotexts: @@ -262,7 +277,13 @@ def process_needpie(app: Sphinx, doctree: nodes.document, fromdocname: str, foun # Legend preparation if current_needpie["legend"]: - axes.legend(wedges, labels, title="legend", loc="center left", bbox_to_anchor=(0.8, 0, 0.5, 1)) + axes.legend( + wedges, + labels, + title="legend", + loc="center left", + bbox_to_anchor=(0.8, 0, 0.5, 1), + ) matplotlib.pyplot.setp(autotexts, size=8, weight="bold") @@ -273,13 +294,17 @@ def process_needpie(app: Sphinx, doctree: nodes.document, fromdocname: str, foun # We need to calculate an unique pie-image file name hash_value = hashlib.sha256(id.encode()).hexdigest()[:5] - image_node = save_matplotlib_figure(app, fig, f"need_pie_{hash_value}", fromdocname) + image_node = save_matplotlib_figure( + app, fig, f"need_pie_{hash_value}", fromdocname + ) # Add lineno to node image_node.line = current_needpie["lineno"] if len(sizes) == 0 or all(s == 0 for s in sizes): - node.replace_self(no_needs_found_paragraph(current_needpie.get("filter_warning"))) + node.replace_self( + no_needs_found_paragraph(current_needpie.get("filter_warning")) + ) else: node.replace_self(image_node) diff --git a/sphinx_needs/directives/needreport.py b/sphinx_needs/directives/needreport.py index 97f4b5c08..516a70abe 100644 --- a/sphinx_needs/directives/needreport.py +++ b/sphinx_needs/directives/needreport.py @@ -49,12 +49,18 @@ def run(self) -> Sequence[nodes.raw]: report_info.update(**needs_config.render_context) if "template" in self.options: - need_report_template_path = Path(self.env.relfn2path(self.options["template"], self.env.docname)[1]) + need_report_template_path = Path( + self.env.relfn2path(self.options["template"], self.env.docname)[1] + ) elif needs_config.report_template: # Absolute path starts with /, based on the conf.py directory. The / need to be striped - need_report_template_path = Path(str(env.app.srcdir)) / needs_config.report_template.lstrip("/") + need_report_template_path = Path( + str(env.app.srcdir) + ) / needs_config.report_template.lstrip("/") else: - need_report_template_path = Path(__file__).parent / "needreport_template.rst" + need_report_template_path = ( + Path(__file__).parent / "needreport_template.rst" + ) if not need_report_template_path.is_file(): LOGGER.warning( @@ -65,11 +71,15 @@ def run(self) -> Sequence[nodes.raw]: ) return [] - needs_report_template_file_content = need_report_template_path.read_text(encoding="utf8") + needs_report_template_file_content = need_report_template_path.read_text( + encoding="utf8" + ) template = Template(needs_report_template_file_content, autoescape=True) text = template.render(**report_info) - self.state_machine.insert_input(text.split("\n"), self.state_machine.document.attributes["source"]) + self.state_machine.insert_input( + text.split("\n"), self.state_machine.document.attributes["source"] + ) report_node = nodes.raw() diff --git a/sphinx_needs/directives/needsequence.py b/sphinx_needs/directives/needsequence.py index 42b1e1e25..bba1269dc 100644 --- a/sphinx_needs/directives/needsequence.py +++ b/sphinx_needs/directives/needsequence.py @@ -57,7 +57,8 @@ def run(self) -> Sequence[nodes.Node]: start = self.options.get("start") if start is None or len(start.strip()) == 0: raise NeedSequenceException( - "No valid start option given for needsequence. " "See file {}:{}".format(env.docname, self.lineno) + "No valid start option given for needsequence. " + f"See file {env.docname}:{self.lineno}" ) # Add the needsequence and all needed information @@ -76,7 +77,10 @@ def run(self) -> Sequence[nodes.Node]: def process_needsequence( - app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element] + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], ) -> None: # Replace all needsequence nodes with a list of the collected needs. env = app.env @@ -98,13 +102,17 @@ def process_needsequence( id = node.attributes["ids"][0] current_needsequence = needs_data.get_or_create_sequences()[id] - option_link_types = [link.upper() for link in current_needsequence["link_types"]] + option_link_types = [ + link.upper() for link in current_needsequence["link_types"] + ] for lt in option_link_types: if lt not in link_type_names: logger.warning( "Unknown link type {link_type} in needsequence {flow}. Allowed values:" " {link_types} [needs]".format( - link_type=lt, flow=current_needsequence["target_id"], link_types=",".join(link_type_names) + link_type=lt, + flow=current_needsequence["target_id"], + link_types=",".join(link_type_names), ), type="needs", ) @@ -131,7 +139,9 @@ def process_needsequence( config = current_needsequence["config"] puml_node["uml"] += add_config(config) - start_needs_id = [x.strip() for x in re.split(";|,", current_needsequence["start"])] + start_needs_id = [ + x.strip() for x in re.split(";|,", current_needsequence["start"]) + ] if len(start_needs_id) == 0: # TODO this should be a warning (and not tested) raise NeedSequenceException( @@ -150,9 +160,11 @@ def process_needsequence( need = all_needs_dict[need_id.strip()] except KeyError: raise NeedSequenceException( - "Given {} in needsequence unknown." - " File {}" - ":{}".format(need_id, current_needsequence["docname"], current_needsequence["lineno"]) + "Given {} in needsequence unknown." " File {}" ":{}".format( + need_id, + current_needsequence["docname"], + current_needsequence["lineno"], + ) ) # Add children of participants @@ -177,7 +189,9 @@ def process_needsequence( puml_node["uml"] += "\n@enduml" puml_node["incdir"] = os.path.dirname(current_needsequence["docname"]) - puml_node["filename"] = os.path.split(current_needsequence["docname"])[1] # Needed for plantuml >= 0.9 + puml_node["filename"] = os.path.split(current_needsequence["docname"])[ + 1 + ] # Needed for plantuml >= 0.9 scale = int(current_needsequence["scale"]) # if scale != 100: @@ -203,8 +217,12 @@ def process_needsequence( gen_flow_link = generate_name(app, puml_node.children[0], file_ext) current_file_parts = fromdocname.split("/") subfolder_amount = len(current_file_parts) - 1 - img_locaton = "../" * subfolder_amount + "_images/" + gen_flow_link[0].split("/")[-1] - flow_ref = nodes.reference("t", current_needsequence["caption"], refuri=img_locaton) + img_locaton = ( + "../" * subfolder_amount + "_images/" + gen_flow_link[0].split("/")[-1] + ) + flow_ref = nodes.reference( + "t", current_needsequence["caption"], refuri=img_locaton + ) puml_node += nodes.caption("", "", flow_ref) # Add lineno to node @@ -212,8 +230,12 @@ def process_needsequence( content.append(puml_node) - if len(c_string) == 0 and p_string.count("participant") == 1: # no connections and just one (start) participant - content = [(no_needs_found_paragraph(current_needsequence.get("filter_warning")))] + if ( + len(c_string) == 0 and p_string.count("participant") == 1 + ): # no connections and just one (start) participant + content = [ + (no_needs_found_paragraph(current_needsequence.get("filter_warning"))) + ] if current_needsequence["show_filters"]: content.append(get_filter_para(current_needsequence)) @@ -241,7 +263,11 @@ def get_message_needs( p_string = "" c_string = "" for msg_need in msg_needs: - messages[msg_need["id"]] = {"id": msg_need["id"], "title": msg_need["title"], "receivers": {}} + messages[msg_need["id"]] = { + "id": msg_need["id"], + "title": msg_need["title"], + "receivers": {}, + } if sender["id"] not in tracked_receivers: p_string += 'participant "{}" as {}\n'.format(sender["title"], sender["id"]) tracked_receivers.append(sender["id"]) @@ -252,17 +278,31 @@ def get_message_needs( from sphinx_needs.filter_common import filter_single_need if not filter_single_need( - all_needs_dict[rec_id], NeedsSphinxConfig(app.config), filter, needs=all_needs_dict.values() + all_needs_dict[rec_id], + NeedsSphinxConfig(app.config), + filter, + needs=all_needs_dict.values(), ): continue - rec_data = {"id": rec_id, "title": all_needs_dict[rec_id]["title"], "messages": []} + rec_data = { + "id": rec_id, + "title": all_needs_dict[rec_id]["title"], + "messages": [], + } - c_string += "{} -> {}: {}\n".format(sender["id"], rec_data["id"], msg_need["title"]) + c_string += "{} -> {}: {}\n".format( + sender["id"], rec_data["id"], msg_need["title"] + ) if rec_id not in tracked_receivers: rec_messages, p_string_new, c_string_new = get_message_needs( - app, all_needs_dict[rec_id], link_types, all_needs_dict, tracked_receivers, filter=filter + app, + all_needs_dict[rec_id], + link_types, + all_needs_dict, + tracked_receivers, + filter=filter, ) p_string += p_string_new c_string += c_string_new diff --git a/sphinx_needs/directives/needservice.py b/sphinx_needs/directives/needservice.py index bf234f7fe..73f920b7d 100644 --- a/sphinx_needs/directives/needservice.py +++ b/sphinx_needs/directives/needservice.py @@ -48,7 +48,17 @@ def __init__( state: RSTState, state_machine: RSTStateMachine, ): - super().__init__(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine) + super().__init__( + name, + arguments, + options, + content, + lineno, + content_offset, + block_text, + state, + state_machine, + ) self.log = get_logger(__name__) def run(self) -> Sequence[nodes.Node]: @@ -94,8 +104,12 @@ def run(self) -> Sequence[nodes.Node]: missing_options = {} for element in datum.keys(): defined_options = list(self.__class__.option_spec.keys()) - defined_options.append("content") # Add content, so that it gets not detected as missing - if element not in defined_options and element not in getattr(app.config, "needs_extra_links", []): + defined_options.append( + "content" + ) # Add content, so that it gets not detected as missing + if element not in defined_options and element not in getattr( + app.config, "needs_extra_links", [] + ): missing_options[element] = datum[element] # Finally delete not found options @@ -112,13 +126,25 @@ def run(self) -> Sequence[nodes.Node]: datum.update(options) # ToDo: Tags and Status are not set (but exist in data) - section += add_need(self.env.app, self.state, docname, self.lineno, need_type, need_title, **datum) + section += add_need( + self.env.app, + self.state, + docname, + self.lineno, + need_type, + need_title, + **datum, + ) else: try: service_debug_data = service.debug(self.options) except NotImplementedError: - service_debug_data = {"error": f'Service {service_name} does not support "debug" output.'} - viewer_node = get_data_viewer_node(title="Debug data", data=service_debug_data) + service_debug_data = { + "error": f'Service {service_name} does not support "debug" output.' + } + viewer_node = get_data_viewer_node( + title="Debug data", data=service_debug_data + ) section.append(viewer_node) add_doc(self.env, self.env.docname) diff --git a/sphinx_needs/directives/needtable.py b/sphinx_needs/directives/needtable.py index c05dfb61b..e6c492d79 100644 --- a/sphinx_needs/directives/needtable.py +++ b/sphinx_needs/directives/needtable.py @@ -52,7 +52,9 @@ class NeedtableDirective(FilterBase): def run(self) -> Sequence[nodes.Node]: env = self.env - targetid = "needtable-{docname}-{id}".format(docname=env.docname, id=env.new_serialno("needtable")) + targetid = "needtable-{docname}-{id}".format( + docname=env.docname, id=env.new_serialno("needtable") + ) targetnode = nodes.target("", "", ids=[targetid]) columns_str = str(self.options.get("columns", "")) @@ -68,7 +70,9 @@ def run(self) -> Sequence[nodes.Node]: colwidths = str(self.options.get("colwidths", "")) colwidths_list = [] if colwidths: - colwidths_list = [int(width.strip()) for width in re.split(";|,", colwidths)] + colwidths_list = [ + int(width.strip()) for width in re.split(";|,", colwidths) + ] if len(columns) != len(colwidths_list): raise NeedsInvalidException( f"Amount of elements in colwidths and columns do not match: " @@ -115,7 +119,10 @@ def run(self) -> Sequence[nodes.Node]: @measure_time("needtable") @profile("NEEDTABLE") def process_needtables( - app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element] + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], ) -> None: """ Replace all needtables nodes with a table of filtered nodes. @@ -149,7 +156,9 @@ def process_needtables( id = node.attributes["ids"][0] current_needtable = needs_data.get_or_create_tables()[id] - if current_needtable["style"] == "" or current_needtable["style"].upper() not in ["TABLE", "DATATABLES"]: + if current_needtable["style"] == "" or current_needtable[ + "style" + ].upper() not in ["TABLE", "DATATABLES"]: if needs_config.table_style == "": style = "DATATABLES" else: @@ -199,7 +208,9 @@ def process_needtables( # Perform filtering of needs try: - filtered_needs = process_filters(app, list(all_needs.values()), current_needtable) + filtered_needs = process_filters( + app, list(all_needs.values()), current_needtable + ) except Exception as e: raise e @@ -228,8 +239,12 @@ def sort(need: NeedsInfoType) -> Any: filtered_needs.sort(key=get_sorter(current_needtable["sort"])) for need_info in filtered_needs: - style_row = check_and_get_content(current_needtable["style_row"], need_info, env) - style_row = style_row.replace(" ", "_") # Replace whitespaces with _ to get valid css name + style_row = check_and_get_content( + current_needtable["style_row"], need_info, env + ) + style_row = style_row.replace( + " ", "_" + ) # Replace whitespaces with _ to get valid css name temp_need = need_info.copy() if temp_need["is_need"]: @@ -243,12 +258,26 @@ def sort(need: NeedsInfoType) -> Any: for option, _title in current_needtable["columns"]: if option == "ID": - row += row_col_maker(app, fromdocname, all_needs, temp_need, "id", make_ref=True, prefix=prefix) + row += row_col_maker( + app, + fromdocname, + all_needs, + temp_need, + "id", + make_ref=True, + prefix=prefix, + ) elif option == "TITLE": - row += row_col_maker(app, fromdocname, all_needs, temp_need, "title", prefix=prefix) + row += row_col_maker( + app, fromdocname, all_needs, temp_need, "title", prefix=prefix + ) elif option in link_type_list: link_type = link_type_list[option] - if option in ["INCOMING", link_type["option"].upper() + "_BACK", link_type["incoming"].upper()]: + if option in [ + "INCOMING", + link_type["option"].upper() + "_BACK", + link_type["incoming"].upper(), + ]: row += row_col_maker( app, fromdocname, @@ -259,10 +288,17 @@ def sort(need: NeedsInfoType) -> Any: ) else: row += row_col_maker( - app, fromdocname, all_needs, temp_need, link_type["option"], ref_lookup=True + app, + fromdocname, + all_needs, + temp_need, + link_type["option"], + ref_lookup=True, ) else: - row += row_col_maker(app, fromdocname, all_needs, temp_need, option.lower()) + row += row_col_maker( + app, fromdocname, all_needs, temp_need, option.lower() + ) tbody += row # Need part rows @@ -315,7 +351,9 @@ def sort(need: NeedsInfoType) -> Any: ref_lookup=True, ) else: - row += row_col_maker(app, fromdocname, all_needs, temp_part, option.lower()) + row += row_col_maker( + app, fromdocname, all_needs, temp_part, option.lower() + ) tbody += row diff --git a/sphinx_needs/directives/needuml.py b/sphinx_needs/directives/needuml.py index 0b2efb482..3fd8f3b41 100644 --- a/sphinx_needs/directives/needuml.py +++ b/sphinx_needs/directives/needuml.py @@ -45,10 +45,14 @@ def run(self) -> Sequence[nodes.Node]: env = self.env if self.name == "needarch": - targetid = "needarch-{docname}-{id}".format(docname=env.docname, id=env.new_serialno("needarch")) + targetid = "needarch-{docname}-{id}".format( + docname=env.docname, id=env.new_serialno("needarch") + ) is_arch = True else: - targetid = "needuml-{docname}-{id}".format(docname=env.docname, id=env.new_serialno("needuml")) + targetid = "needuml-{docname}-{id}".format( + docname=env.docname, id=env.new_serialno("needuml") + ) is_arch = False targetnode = nodes.target("", "", ids=[targetid]) @@ -87,7 +91,9 @@ def run(self) -> Sequence[nodes.Node]: plantuml_code_out_path = None if save_path: if os.path.isabs(save_path): - raise NeedumlException(f"Given save path: {save_path}, is not a relative path.") + raise NeedumlException( + f"Given save path: {save_path}, is not a relative path." + ) else: plantuml_code_out_path = save_path @@ -123,7 +129,9 @@ def run(self) -> Sequence[nodes.Node]: return NeedumlDirective.run(self) -def transform_uml_to_plantuml_node(app, uml_content: str, parent_need_id: str, key: str, kwargs: dict, config: str): +def transform_uml_to_plantuml_node( + app, uml_content: str, parent_need_id: str, key: str, kwargs: dict, config: str +): try: if "sphinxcontrib.plantuml" not in app.config.extensions: raise ImportError @@ -178,7 +186,13 @@ def get_debug_node_from_puml_node(puml_node): def jinja2uml( - app, fromdocname, uml_content: str, parent_need_id: str, key: str, processed_need_ids: {}, kwargs: dict + app, + fromdocname, + uml_content: str, + parent_need_id: str, + key: str, + processed_need_ids: {}, + kwargs: dict, ) -> (str, {}): # Let's render jinja templates with uml content template to 'plantuml syntax' uml # 1. Remove @startuml and @enduml @@ -192,7 +206,9 @@ def jinja2uml( # 4. Append need_id to processed_need_ids, so it will not been processed again if parent_need_id: - jinja_utils.append_need_to_processed_needs(need_id=parent_need_id, art="uml", key=key, kwargs=kwargs) + jinja_utils.append_need_to_processed_needs( + need_id=parent_need_id, art="uml", key=key, kwargs=kwargs + ) # 5. Get data for the jinja processing data = {} @@ -229,13 +245,17 @@ class JinjaFunctions: Provides access to sphinx-app and all Needs objects. """ - def __init__(self, app: Sphinx, fromdocname, parent_need_id: str, processed_need_ids: dict): + def __init__( + self, app: Sphinx, fromdocname, parent_need_id: str, processed_need_ids: dict + ): self.needs = SphinxNeedsData(app.env).get_or_create_needs() self.app = app self.fromdocname = fromdocname self.parent_need_id = parent_need_id if parent_need_id and parent_need_id not in self.needs: - raise NeedumlException(f"JinjaFunctions initialized with undefined parent_need_id: '{parent_need_id}'") + raise NeedumlException( + f"JinjaFunctions initialized with undefined parent_need_id: '{parent_need_id}'" + ) self.processed_need_ids = processed_need_ids def need_to_processed_data(self, art: str, key: str, kwargs: dict) -> {}: @@ -246,7 +266,9 @@ def need_to_processed_data(self, art: str, key: str, kwargs: dict) -> {}: } return d - def append_need_to_processed_needs(self, need_id: str, art: str, key: str, kwargs: dict) -> None: + def append_need_to_processed_needs( + self, need_id: str, art: str, key: str, kwargs: dict + ) -> None: data = self.need_to_processed_data(art=art, key=key, kwargs=kwargs) if need_id not in self.processed_need_ids: self.processed_need_ids[need_id] = [] @@ -261,18 +283,26 @@ def append_needs_to_processed_needs(self, processed_needs_data: dict) -> None: if d not in self.processed_need_ids[k]: self.processed_need_ids[k].append(d) - def data_in_processed_data(self, need_id: str, art: str, key: str, kwargs: dict) -> bool: + def data_in_processed_data( + self, need_id: str, art: str, key: str, kwargs: dict + ) -> bool: data = self.need_to_processed_data(art=art, key=key, kwargs=kwargs) - return (need_id in self.processed_need_ids) and (data in self.processed_need_ids[need_id]) + return (need_id in self.processed_need_ids) and ( + data in self.processed_need_ids[need_id] + ) def get_processed_need_ids(self) -> {}: return self.processed_need_ids def uml_from_need(self, need_id: str, key: str = "diagram", **kwargs) -> str: if need_id not in self.needs: - raise NeedumlException(f"Jinja function uml() is called with undefined need_id: '{need_id}'.") + raise NeedumlException( + f"Jinja function uml() is called with undefined need_id: '{need_id}'." + ) - if self.data_in_processed_data(need_id=need_id, art="uml", key=key, kwargs=kwargs): + if self.data_in_processed_data( + need_id=need_id, art="uml", key=key, kwargs=kwargs + ): return "" need_info = self.needs[need_id] @@ -281,7 +311,9 @@ def uml_from_need(self, need_id: str, key: str = "diagram", **kwargs) -> str: if need_info["arch"][key]: uml_content = need_info["arch"][key] else: - raise NeedumlException(f"Option key name: {key} does not exist in need {need_id}.") + raise NeedumlException( + f"Option key name: {key} does not exist in need {need_id}." + ) else: if "diagram" in need_info["arch"] and need_info["arch"]["diagram"]: uml_content = need_info["arch"]["diagram"] @@ -307,13 +339,17 @@ def uml_from_need(self, need_id: str, key: str = "diagram", **kwargs) -> str: def flow(self, need_id) -> str: if need_id not in self.needs: - raise NeedumlException(f"Jinja function flow is called with undefined need_id: '{need_id}'.") + raise NeedumlException( + f"Jinja function flow is called with undefined need_id: '{need_id}'." + ) if self.data_in_processed_data(need_id=need_id, art="flow", key="", kwargs={}): return "" # append need_id to processed_need_ids, so it will not been processed again - self.append_need_to_processed_needs(need_id=need_id, art="flow", key="", kwargs={}) + self.append_need_to_processed_needs( + need_id=need_id, art="flow", key="", kwargs={} + ) need_info = self.needs[need_id] link = calculate_link(self.app, need_info, self.fromdocname) @@ -334,9 +370,13 @@ def flow(self, need_id) -> str: def ref(self, need_id: str, option: str = None, text: str = None) -> str: if need_id not in self.needs: - raise NeedumlException(f"Jinja function ref is called with undefined need_id: '{need_id}'.") + raise NeedumlException( + f"Jinja function ref is called with undefined need_id: '{need_id}'." + ) if (option and text) and (not option and not text): - raise NeedumlException("Jinja function ref requires exactly one entry 'option' or 'text'") + raise NeedumlException( + "Jinja function ref requires exactly one entry 'option' or 'text'" + ) need_info = self.needs[need_id] link = calculate_link(self.app, need_info, self.fromdocname) @@ -354,11 +394,15 @@ def filter(self, filter_string): """ needs_config = NeedsSphinxConfig(self.app.config) - return filter_needs(list(self.needs.values()), needs_config, filter_string=filter_string) + return filter_needs( + list(self.needs.values()), needs_config, filter_string=filter_string + ) def imports(self, *args): if not self.parent_need_id: - raise NeedumlException("Jinja function 'import()' is not supported in needuml directive.") + raise NeedumlException( + "Jinja function 'import()' is not supported in needuml directive." + ) # gets all need ids from need links/extra_links options and wrap into jinja function uml() need_info = self.needs[self.parent_need_id] uml_ids = [] @@ -378,7 +422,9 @@ def imports(self, *args): def need(self): if not self.parent_need_id: - raise NeedumlException("Jinja function 'need()' is not supported in needuml directive.") + raise NeedumlException( + "Jinja function 'need()' is not supported in needuml directive." + ) return self.needs[self.parent_need_id] @@ -407,7 +453,12 @@ def is_element_of_need(node: nodes.Element) -> str: @measure_time("needuml") -def process_needuml(app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element]) -> None: +def process_needuml( + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], +) -> None: env = app.env # for node in doctree.findall(Needuml): @@ -421,14 +472,18 @@ def process_needuml(app: Sphinx, doctree: nodes.document, fromdocname: str, foun # Check if needarch is only used inside a need parent_need_id = is_element_of_need(node) if not parent_need_id: - raise NeedArchException("Directive needarch can only be used inside a need.") + raise NeedArchException( + "Directive needarch can only be used inside a need." + ) content = [] # Adding config config = current_needuml["config"] if config and len(config) >= 3: # Remove all empty lines - config = "\n".join([line.strip() for line in config.split("\n") if line.strip()]) + config = "\n".join( + [line.strip() for line in config.split("\n") if line.strip()] + ) puml_node = transform_uml_to_plantuml_node( app=app, @@ -459,7 +514,9 @@ def process_needuml(app: Sphinx, doctree: nodes.document, fromdocname: str, foun puml_node["align"] = "center" puml_node["incdir"] = os.path.dirname(current_needuml["docname"]) - puml_node["filename"] = os.path.split(current_needuml["docname"])[1] # Needed for plantuml >= 0.9 + puml_node["filename"] = os.path.split(current_needuml["docname"])[ + 1 + ] # Needed for plantuml >= 0.9 content.append(puml_node) diff --git a/sphinx_needs/directives/utils.py b/sphinx_needs/directives/utils.py index 378342909..abb3b891b 100644 --- a/sphinx_needs/directives/utils.py +++ b/sphinx_needs/directives/utils.py @@ -24,17 +24,25 @@ def used_filter_paragraph(current_needfilter: NeedsFilteredBaseType) -> nodes.pa para = nodes.paragraph() filter_text = "Used filter:" filter_text += ( - " status(%s)" % " OR ".join(current_needfilter["status"]) if len(current_needfilter["status"]) > 0 else "" + " status(%s)" % " OR ".join(current_needfilter["status"]) + if len(current_needfilter["status"]) > 0 + else "" ) if len(current_needfilter["status"]) > 0 and len(current_needfilter["tags"]) > 0: filter_text += " AND " - filter_text += " tags(%s)" % " OR ".join(current_needfilter["tags"]) if len(current_needfilter["tags"]) > 0 else "" - if (len(current_needfilter["status"]) > 0 or len(current_needfilter["tags"]) > 0) and len( - current_needfilter["types"] - ) > 0: + filter_text += ( + " tags(%s)" % " OR ".join(current_needfilter["tags"]) + if len(current_needfilter["tags"]) > 0 + else "" + ) + if ( + len(current_needfilter["status"]) > 0 or len(current_needfilter["tags"]) > 0 + ) and len(current_needfilter["types"]) > 0: filter_text += " AND " filter_text += ( - " types(%s)" % " OR ".join(current_needfilter["types"]) if len(current_needfilter["types"]) > 0 else "" + " types(%s)" % " OR ".join(current_needfilter["types"]) + if len(current_needfilter["types"]) > 0 + else "" ) filter_node = nodes.emphasis(filter_text, filter_text) @@ -91,7 +99,9 @@ def analyse_needs_metrics(env: BuildEnvironment) -> dict[str, Any]: if i["type"] in needs_types: needs_types[i["type"]] += 1 - metric_data["needs_types"] = {i[0]: i[1] for i in sorted(needs_types.items(), key=lambda x: x[0])} + metric_data["needs_types"] = { + i[0]: i[1] for i in sorted(needs_types.items(), key=lambda x: x[0]) + } return metric_data diff --git a/sphinx_needs/environment.py b/sphinx_needs/environment.py index 61dbf95dc..786ea2666 100644 --- a/sphinx_needs/environment.py +++ b/sphinx_needs/environment.py @@ -40,13 +40,21 @@ def safe_add_file(filename: Path, app: Sphinx) -> None: if pure_path.suffix == ".js": # Make sure the calculated (posix)-path is not already registered as "web"-path - if hasattr(builder, "script_files") and str(static_data_file) not in builder.script_files: + if ( + hasattr(builder, "script_files") + and str(static_data_file) not in builder.script_files + ): app.add_js_file(str(pure_path)) elif pure_path.suffix == ".css": - if hasattr(builder, "css_files") and str(static_data_file) not in builder.css_files: + if ( + hasattr(builder, "css_files") + and str(static_data_file) not in builder.css_files + ): app.add_css_file(str(pure_path)) else: - raise NotImplementedError(f"File type {pure_path.suffix} not support by save_add_file") + raise NotImplementedError( + f"File type {pure_path.suffix} not support by save_add_file" + ) def safe_remove_file(filename: Path, app: Sphinx) -> None: @@ -120,7 +128,10 @@ def _find_css_files() -> Iterable[Path]: if not source_file_path.exists(): source_file_path = css_root / "blank" / "blank.css" - logger.warning(f"{source_file_path} not found. Copying sphinx-internal blank.css [needs]", type="needs") + logger.warning( + f"{source_file_path} not found. Copying sphinx-internal blank.css [needs]", + type="needs", + ) dest_file = dest_dir / source_file_path.name dest_dir.mkdir(exist_ok=True) @@ -215,7 +226,9 @@ def install_permalink_file(app: Sphinx, env: BuildEnvironment) -> None: return # load jinja template - jinja_env = Environment(loader=PackageLoader("sphinx_needs"), autoescape=select_autoescape()) + jinja_env = Environment( + loader=PackageLoader("sphinx_needs"), autoescape=select_autoescape() + ) template = jinja_env.get_template("permalink.html") # save file to build dir diff --git a/sphinx_needs/external_needs.py b/sphinx_needs/external_needs.py index fc8003648..331038996 100644 --- a/sphinx_needs/external_needs.py +++ b/sphinx_needs/external_needs.py @@ -47,18 +47,28 @@ def load_external_needs(app: Sphinx, env: BuildEnvironment, _docname: str) -> No ) ) elif not (source.get("json_url", False) or source.get("json_path", False)): - raise NeedsExternalException("json_path or json_url must be configured to use external_needs.") + raise NeedsExternalException( + "json_path or json_url must be configured to use external_needs." + ) if source.get("json_url", False): - log.info(clean_log(f"Loading external needs from url {source['json_url']}.")) + log.info( + clean_log(f"Loading external needs from url {source['json_url']}.") + ) s = requests.Session() s.mount("file://", FileAdapter()) try: response = s.get(source["json_url"]) - needs_json = response.json() # The downloaded file MUST be json. Everything else we do not handle! + needs_json = ( + response.json() + ) # The downloaded file MUST be json. Everything else we do not handle! except Exception as e: raise NeedsExternalException( - clean_log("Getting {} didn't work. Reason: {}".format(source["json_url"], e)) + clean_log( + "Getting {} didn't work. Reason: {}".format( + source["json_url"], e + ) + ) ) if source.get("json_path", False): @@ -68,7 +78,9 @@ def load_external_needs(app: Sphinx, env: BuildEnvironment, _docname: str) -> No json_path = os.path.join(app.srcdir, source["json_path"]) if not os.path.exists(json_path): - raise NeedsExternalException(f"Given json_path {json_path} does not exist.") + raise NeedsExternalException( + f"Given json_path {json_path} does not exist." + ) with open(json_path) as json_file: needs_json = json.load(json_file) @@ -83,7 +95,9 @@ def load_external_needs(app: Sphinx, env: BuildEnvironment, _docname: str) -> No needs = needs_json["versions"][version]["needs"] except KeyError: raise NeedsExternalException( - clean_log(f"Version {version} not found in json file from {source['json_url']}") + clean_log( + f"Version {version} not found in json file from {source['json_url']}" + ) ) log.debug(f"Loading {len(needs)} needs.") @@ -98,7 +112,16 @@ def load_external_needs(app: Sphinx, env: BuildEnvironment, _docname: str) -> No if ( key not in needs_config.extra_options and key not in extra_links - and key not in ["title", "type", "id", "description", "tags", "docname", "status"] + and key + not in [ + "title", + "type", + "id", + "description", + "tags", + "docname", + "status", + ] ): del need_params[key] @@ -112,9 +135,9 @@ def load_external_needs(app: Sphinx, env: BuildEnvironment, _docname: str) -> No cal_target_url = mem_template.render(**{"need": need}) need_params["external_url"] = f'{source["base_url"]}/{cal_target_url}' else: - need_params["external_url"] = ( - f'{source["base_url"]}/{need.get("docname", "__error__")}.html#{need["id"]}' - ) + need_params[ + "external_url" + ] = f'{source["base_url"]}/{need.get("docname", "__error__")}.html#{need["id"]}' need_params["content"] = need["description"] need_params["links"] = need.get("links", []) diff --git a/sphinx_needs/filter_common.py b/sphinx_needs/filter_common.py index 896256860..0ba740372 100644 --- a/sphinx_needs/filter_common.py +++ b/sphinx_needs/filter_common.py @@ -55,7 +55,11 @@ class FilterBase(SphinxDirective): def collect_filter_attributes(self) -> FilterAttributesType: _tags = str(self.options.get("tags", "")) - tags = [tag.strip() for tag in re.split(";|,", _tags) if len(tag) > 0] if _tags else [] + tags = ( + [tag.strip() for tag in re.split(";|,", _tags) if len(tag) > 0] + if _tags + else [] + ) status = self.options.get("status") if status: @@ -92,7 +96,10 @@ def collect_filter_attributes(self) -> FilterAttributesType: def process_filters( - app: Sphinx, all_needs: Iterable[NeedsInfoType], filter_data: NeedsFilteredBaseType, include_external: bool = True + app: Sphinx, + all_needs: Iterable[NeedsInfoType], + filter_data: NeedsFilteredBaseType, + include_external: bool = True, ) -> list[NeedsPartsInfoType]: """ Filters all needs with given configuration. @@ -112,7 +119,10 @@ def process_filters( try: all_needs = sorted(all_needs, key=lambda node: node[sort_key] or "") # type: ignore[literal-required] except KeyError as e: - log.warning(f"Sorting parameter {sort_key} not valid: Error: {e} [needs]", type="needs") + log.warning( + f"Sorting parameter {sort_key} not valid: Error: {e} [needs]", + type="needs", + ) # check if include external needs checked_all_needs: Iterable[NeedsInfoType] @@ -130,7 +140,9 @@ def process_filters( all_needs_incl_parts = prepare_need_list(checked_all_needs) # Check if external filter code is defined - filter_func, filter_args = check_and_get_external_filter_func(filter_data.get("filter_func")) + filter_func, filter_args = check_and_get_external_filter_func( + filter_data.get("filter_func") + ) filter_code = None # Get filter_code from @@ -141,12 +153,19 @@ def process_filters( if bool(filter_data["status"] or filter_data["tags"] or filter_data["types"]): for need_info in all_needs_incl_parts: status_filter_passed = False - if not filter_data["status"] or need_info["status"] and need_info["status"] in filter_data["status"]: + if ( + not filter_data["status"] + or need_info["status"] + and need_info["status"] in filter_data["status"] + ): # Filtering for status was not requested or match was found status_filter_passed = True tags_filter_passed = False - if len(set(need_info["tags"]) & set(filter_data["tags"])) > 0 or len(filter_data["tags"]) == 0: + if ( + len(set(need_info["tags"]) & set(filter_data["tags"])) > 0 + or len(filter_data["tags"]) == 0 + ): tags_filter_passed = True type_filter_passed = False @@ -160,13 +179,19 @@ def process_filters( if status_filter_passed and tags_filter_passed and type_filter_passed: found_needs_by_options.append(need_info) # Get need by filter string - found_needs_by_string = filter_needs(all_needs_incl_parts, needs_config, filter_data["filter"]) + found_needs_by_string = filter_needs( + all_needs_incl_parts, needs_config, filter_data["filter"] + ) # Make an intersection of both lists - found_needs = intersection_of_need_results(found_needs_by_options, found_needs_by_string) + found_needs = intersection_of_need_results( + found_needs_by_options, found_needs_by_string + ) else: # There is no other config as the one for filter string. # So we only need this result. - found_needs = filter_needs(all_needs_incl_parts, needs_config, filter_data["filter"]) + found_needs = filter_needs( + all_needs_incl_parts, needs_config, filter_data["filter"] + ) else: # Provides only a copy of needs to avoid data manipulations. context = { @@ -185,7 +210,9 @@ def process_filters( context[f"arg{index+1}"] = arg # Decorate function to allow time measurments - filter_func = measure_time_func(filter_func, category="filter_func", source="user") + filter_func = measure_time_func( + filter_func, category="filter_func", source="user" + ) filter_func(**context) else: log.warning("Something went wrong running filter [needs]", type="needs") @@ -237,7 +264,11 @@ def prepare_need_list(need_list: Iterable[NeedsInfoType]) -> list[NeedsPartsInfo for need in need_list: for part in need["parts"].values(): id_complete = ".".join([need["id"], part["id"]]) - filter_part: NeedsPartsInfoType = {**need, **part, **{"id_parent": need["id"], "id_complete": id_complete}} # type: ignore[typeddict-item] + filter_part: NeedsPartsInfoType = { + **need, + **part, + **{"id_parent": need["id"], "id_complete": id_complete}, # type: ignore[typeddict-item] + } all_needs_incl_parts.append(filter_part) # Be sure extra attributes, which makes only sense for need_parts, are also available on @@ -288,12 +319,21 @@ def filter_needs( for filter_need in needs: try: if filter_single_need( - filter_need, config, filter_string, needs, current_need, filter_compiled=filter_compiled + filter_need, + config, + filter_string, + needs, + current_need, + filter_compiled=filter_compiled, ): found_needs.append(filter_need) except Exception as e: if not error_reported: # Let's report a filter-problem only onces - location = (current_need["docname"], current_need["lineno"]) if current_need else None + location = ( + (current_need["docname"], current_need["lineno"]) + if current_need + else None + ) log.warning(str(e) + " [needs]", type="needs", location=location) error_reported = True diff --git a/sphinx_needs/functions/common.py b/sphinx_needs/functions/common.py index f5d96bf06..467743294 100644 --- a/sphinx_needs/functions/common.py +++ b/sphinx_needs/functions/common.py @@ -19,7 +19,13 @@ from sphinx_needs.utils import logger -def test(app: Sphinx, need: NeedsInfoType, needs: dict[str, NeedsInfoType], *args: Any, **kwargs: Any) -> str: +def test( + app: Sphinx, + need: NeedsInfoType, + needs: dict[str, NeedsInfoType], + *args: Any, + **kwargs: Any, +) -> str: """ Test function for dynamic functions in sphinx needs. @@ -41,7 +47,12 @@ def test(app: Sphinx, need: NeedsInfoType, needs: dict[str, NeedsInfoType], *arg def echo( - app: Sphinx, need: NeedsInfoType, needs: dict[str, NeedsInfoType], text: str, *args: Any, **kwargs: Any + app: Sphinx, + need: NeedsInfoType, + needs: dict[str, NeedsInfoType], + text: str, + *args: Any, + **kwargs: Any, ) -> str: """ .. versionadded:: 0.6.3 @@ -154,7 +165,9 @@ def copy( need = needs[need_id] if filter: - result = filter_needs(needs.values(), NeedsSphinxConfig(app.config), filter, need) + result = filter_needs( + needs.values(), NeedsSphinxConfig(app.config), filter, need + ) if result: need = result[0] @@ -323,7 +336,10 @@ def check_linked_values( if not filter_single_need(need, needs_config, filter_string): continue except Exception as e: - logger.warning(f"CheckLinkedValues: Filter {filter_string} not valid: Error: {e} [needs]", type="needs") + logger.warning( + f"CheckLinkedValues: Filter {filter_string} not valid: Error: {e} [needs]", + type="needs", + ) need_value = need[search_option] # type: ignore[literal-required] if not one_hit and need_value not in search_value: @@ -422,7 +438,9 @@ def calc_sum( :return: A float number """ needs_config = NeedsSphinxConfig(app.config) - check_needs = [needs[link] for link in need["links"]] if links_only else needs.values() + check_needs = ( + [needs[link] for link in need["links"]] if links_only else needs.values() + ) calculated_sum = 0.0 @@ -434,7 +452,9 @@ def calc_sum( except ValueError: pass except NeedsInvalidFilter as ex: - logger.warning(f"Given filter is not valid. Error: {ex} [needs]", type="needs") + logger.warning( + f"Given filter is not valid. Error: {ex} [needs]", type="needs" + ) with contextlib.suppress(ValueError): calculated_sum += float(check_need[option]) # type: ignore[literal-required] @@ -514,7 +534,9 @@ def links_from_content( needs_config = NeedsSphinxConfig(app.config) filtered_links = [] for link in raw_links: - if link not in filtered_links and filter_single_need(needs[link], needs_config, filter): + if link not in filtered_links and filter_single_need( + needs[link], needs_config, filter + ): filtered_links.append(link) return filtered_links diff --git a/sphinx_needs/functions/functions.py b/sphinx_needs/functions/functions.py index 694435d17..32ead7438 100644 --- a/sphinx_needs/functions/functions.py +++ b/sphinx_needs/functions/functions.py @@ -29,7 +29,8 @@ # TODO these functions also take optional *args and **kwargs DynamicFunction = Callable[ - [Sphinx, NeedsInfoType, Dict[str, NeedsInfoType]], Union[str, int, float, List[Union[str, int, float]]] + [Sphinx, NeedsInfoType, Dict[str, NeedsInfoType]], + Union[str, int, float, List[Union[str, int, float]]], ] @@ -55,7 +56,9 @@ def register_func(need_function: DynamicFunction, name: str | None = None) -> No # We can not throw an exception here, as using sphinx-needs in different sphinx-projects with the # same python interpreter session does not clean NEEDS_FUNCTIONS. # This is mostly the case during tet runs. - logger.info(f"sphinx-needs: Function name {func_name} already registered. Ignoring the new one!") + logger.info( + f"sphinx-needs: Function name {func_name} already registered. Ignoring the new one!" + ) NEEDS_FUNCTIONS[func_name] = {"name": func_name, "function": need_function} @@ -72,10 +75,22 @@ def execute_func(app: Sphinx, need: NeedsInfoType, func_string: str) -> Any: func_name, func_args, func_kwargs = _analyze_func_string(func_string, need) if func_name not in NEEDS_FUNCTIONS: - raise SphinxError("Unknown dynamic sphinx-needs function: {}. Found in need: {}".format(func_name, need["id"])) + raise SphinxError( + "Unknown dynamic sphinx-needs function: {}. Found in need: {}".format( + func_name, need["id"] + ) + ) - func = measure_time_func(NEEDS_FUNCTIONS[func_name]["function"], category="dyn_func", source="user") - func_return = func(app, need, SphinxNeedsData(app.env).get_or_create_needs(), *func_args, **func_kwargs) + func = measure_time_func( + NEEDS_FUNCTIONS[func_name]["function"], category="dyn_func", source="user" + ) + func_return = func( + app, + need, + SphinxNeedsData(app.env).get_or_create_needs(), + *func_args, + **func_kwargs, + ) if not isinstance(func_return, (str, int, float, list, unicode)) and func_return: raise SphinxError( @@ -97,7 +112,9 @@ def execute_func(app: Sphinx, need: NeedsInfoType, func_string: str) -> Any: func_pattern = re.compile(r"\[\[(.*?)\]\]") # RegEx to detect function strings -def find_and_replace_node_content(node: nodes.Node, env: BuildEnvironment, need: NeedsInfoType) -> nodes.Node: +def find_and_replace_node_content( + node: nodes.Node, env: BuildEnvironment, need: NeedsInfoType +) -> nodes.Node: """ Search inside a given node and its children for nodes of type Text, if found, check if it contains a function string and run/replace it. @@ -106,7 +123,11 @@ def find_and_replace_node_content(node: nodes.Node, env: BuildEnvironment, need: :return: None """ new_children = [] - if not node.children and isinstance(node, nodes.Text) or isinstance(node, nodes.reference): + if ( + not node.children + and isinstance(node, nodes.Text) + or isinstance(node, nodes.reference) + ): if isinstance(node, nodes.reference): try: new_text = node.attributes["refuri"] @@ -127,8 +148,8 @@ def find_and_replace_node_content(node: nodes.Node, env: BuildEnvironment, need: func_string = func_string.replace("”", '"') func_string = func_string.replace("”", '"') - func_string = func_string.replace("‘", "'") - func_string = func_string.replace("’", "'") + func_string = func_string.replace("‘", "'") # noqa: RUF001 + func_string = func_string.replace("’", "'") # noqa: RUF001 func_return = execute_func(env.app, need, func_string) # This should never happen, but we can not be sure. @@ -176,20 +197,30 @@ def resolve_dynamic_values(needs: dict[str, NeedsInfoType], app: Sphinx) -> None """ for need in needs.values(): for need_option in need: - if need_option in ["docname", "lineno", "content", "content_node", "content_id"]: + if need_option in [ + "docname", + "lineno", + "content", + "content_node", + "content_id", + ]: # dynamic values in this data are not allowed. continue if not isinstance(need[need_option], (list, set)): func_call: str | None = "init" while func_call: try: - func_call, func_return = _detect_and_execute(need[need_option], need, app) + func_call, func_return = _detect_and_execute( + need[need_option], need, app + ) except FunctionParsingException: raise SphinxError( "Function definition of {option} in file {file}:{line} has " "unsupported parameters. " "supported are str, int/float, list".format( - option=need_option, file=need["docname"], line=need["lineno"] + option=need_option, + file=need["docname"], + line=need["lineno"], ) ) @@ -197,9 +228,13 @@ def resolve_dynamic_values(needs: dict[str, NeedsInfoType], app: Sphinx) -> None continue # Replace original function string with return value of function call if func_return is None: - need[need_option] = need[need_option].replace(f"[[{func_call}]]", "") + need[need_option] = need[need_option].replace( + f"[[{func_call}]]", "" + ) else: - need[need_option] = need[need_option].replace(f"[[{func_call}]]", str(func_return)) + need[need_option] = need[need_option].replace( + f"[[{func_call}]]", str(func_return) + ) if need[need_option] == "": need[need_option] = None @@ -213,7 +248,9 @@ def resolve_dynamic_values(needs: dict[str, NeedsInfoType], app: Sphinx) -> None "Function definition of {option} in file {file}:{line} has " "unsupported parameters. " "supported are str, int/float, list".format( - option=need_option, file=need["docname"], line=need["lineno"] + option=need_option, + file=need["docname"], + line=need["lineno"], ) ) if func_call is None: @@ -221,7 +258,9 @@ def resolve_dynamic_values(needs: dict[str, NeedsInfoType], app: Sphinx) -> None else: # Replace original function string with return value of function call if isinstance(need[need_option], (str, int, float)): - new_values.append(element.replace(f"[[{func_call}]]", str(func_return))) + new_values.append( + element.replace(f"[[{func_call}]]", str(func_return)) + ) else: if isinstance(need[need_option], (list, set)): if isinstance(func_return, (list, set)): @@ -233,7 +272,9 @@ def resolve_dynamic_values(needs: dict[str, NeedsInfoType], app: Sphinx) -> None def resolve_variants_options( - needs: dict[str, NeedsInfoType], needs_config: NeedsSphinxConfig, tags: dict[str, bool] + needs: dict[str, NeedsInfoType], + needs_config: NeedsSphinxConfig, + tags: dict[str, bool], ) -> None: """ Resolve variants options inside need data. @@ -255,20 +296,28 @@ def resolve_variants_options( for need in needs.values(): # Data to use as filter context. need_context: dict[str, Any] = {**need} - need_context.update(**needs_config.filter_data) # Add needs_filter_data to filter context + need_context.update( + **needs_config.filter_data + ) # Add needs_filter_data to filter context need_context.update(**tags) # Add sphinx tags to filter context for var_option in variants_options: if var_option in need and need[var_option] not in (None, "", []): if not isinstance(need[var_option], (list, set, tuple)): option_value: str = need[var_option] - need[var_option] = match_variants(option_value, need_context, needs_config.variants) + need[var_option] = match_variants( + option_value, need_context, needs_config.variants + ) else: option_value = need[var_option] - need[var_option] = match_variants(option_value, need_context, needs_config.variants) + need[var_option] = match_variants( + option_value, need_context, needs_config.variants + ) -def check_and_get_content(content: str, need: NeedsInfoType, env: BuildEnvironment) -> str: +def check_and_get_content( + content: str, need: NeedsInfoType, env: BuildEnvironment +) -> str: """ Checks if the given content is a function call. If not, content is returned. @@ -290,14 +339,18 @@ def check_and_get_content(content: str, need: NeedsInfoType, env: BuildEnvironme return content func_call = func_match.group(1) # Extract function call - func_return = execute_func(env.app, need, func_call) # Execute function call and get return value + func_return = execute_func( + env.app, need, func_call + ) # Execute function call and get return value # Replace the function_call with the calculated value content = content.replace(f"[[{func_call}]]", func_return) return content -def _detect_and_execute(content: Any, need: NeedsInfoType, app: Sphinx) -> tuple[str | None, Any]: +def _detect_and_execute( + content: Any, need: NeedsInfoType, app: Sphinx +) -> tuple[str | None, Any]: """Detects if given content is a function call and executes it.""" try: content = str(content) @@ -309,12 +362,16 @@ def _detect_and_execute(content: Any, need: NeedsInfoType, app: Sphinx) -> tuple return None, None func_call = func_match.group(1) # Extract function call - func_return = execute_func(app, need, func_call) # Execute function call and get return value + func_return = execute_func( + app, need, func_call + ) # Execute function call and get return value return func_call, func_return -def _analyze_func_string(func_string: str, need: NeedsInfoType | None) -> tuple[str, list[Any], dict[str, Any]]: +def _analyze_func_string( + func_string: str, need: NeedsInfoType | None +) -> tuple[str, list[Any], dict[str, Any]]: """ Analyze given function string and extract: @@ -331,12 +388,16 @@ def _analyze_func_string(func_string: str, need: NeedsInfoType | None) -> tuple[ func = ast.parse(func_string) except SyntaxError as e: need_id = need["id"] if need else "UNKNOWN" - raise SphinxError(f"Parsing function string failed for need {need_id}: {func_string}. {e}") + raise SphinxError( + f"Parsing function string failed for need {need_id}: {func_string}. {e}" + ) try: func_call = func.body[0].value # type: ignore func_name = func_call.func.id except AttributeError: - raise SphinxError(f"Given dynamic function string is not a valid python call. Got: {func_string}") + raise SphinxError( + f"Given dynamic function string is not a valid python call. Got: {func_string}" + ) func_args: list[Any] = [] for arg in func_call.args: @@ -366,8 +427,8 @@ def _analyze_func_string(func_string: str, need: NeedsInfoType | None) -> tuple[ ) else: raise FunctionParsingException( - "Unsupported type found in function definition: {}. " - "Supported are numbers, strings, bool and list".format(func_string) + f"Unsupported type found in function definition: {func_string}. " + "Supported are numbers, strings, bool and list" ) func_kargs: dict[str, Any] = {} for keyword in func_call.keywords: diff --git a/sphinx_needs/layout.py b/sphinx_needs/layout.py index d9c573945..e7cc60e35 100644 --- a/sphinx_needs/layout.py +++ b/sphinx_needs/layout.py @@ -33,7 +33,11 @@ @measure_time("need") def create_need( - need_id: str, app: Sphinx, layout: str | None = None, style: str | None = None, docname: str | None = None + need_id: str, + app: Sphinx, + layout: str | None = None, + style: str | None = None, + docname: str | None = None, ) -> nodes.container: """ Creates a new need-node for a given layout. @@ -78,7 +82,9 @@ def create_need( # Overwrite the docname, which must be the original one from the reused need, as all used paths are relative # to the original location, not to the current document. - env.temp_data["docname"] = need_data["docname"] # Dirty, as in this phase normally no docname is set anymore in env + env.temp_data["docname"] = need_data[ + "docname" + ] # Dirty, as in this phase normally no docname is set anymore in env ImageCollector().process_doc(app, node_inner) # type: ignore[arg-type] DownloadFileCollector().process_doc(app, node_inner) # type: ignore[arg-type] @@ -102,7 +108,9 @@ def create_need( # set the layout and style for the new need node_container[0].attributes = node_container.parent.children[0].attributes # type: ignore - node_container[0].children[0].attributes = node_container.parent.children[0].children[0].attributes # type: ignore + node_container[0].children[0].attributes = ( # type: ignore + node_container.parent.children[0].children[0].attributes # type: ignore + ) node_container.attributes["ids"] = [] @@ -129,7 +137,11 @@ def replace_pending_xref_refdoc(node: nodes.Element, new_refdoc: str) -> None: @measure_time("need") def build_need( - layout: str, node: nodes.Element, app: Sphinx, style: str | None = None, fromdocname: str | None = None + layout: str, + node: nodes.Element, + app: Sphinx, + style: str | None = None, + fromdocname: str | None = None, ) -> None: """ Builds a need based on a given layout for a given need-node. @@ -221,7 +233,11 @@ def __init__( self.fromdocname = fromdocname # For ReadTheDocs Theme we need to add 'rtd-exclude-wy-table'. - classes = ["need", "needs_grid_" + self.layout["grid"], "needs_layout_" + self.layout_name] + classes = [ + "need", + "needs_grid_" + self.layout["grid"], + "needs_layout_" + self.layout_name, + ] classes.extend(self.needs_config.table_classes) self.style = style or self.need["style"] or self.needs_config.default_style @@ -241,59 +257,121 @@ def __init__( self.grids = { "simple": { "func": self._grid_simple, - "configs": {"colwidths": [100], "side_left": False, "side_right": False, "footer": False}, + "configs": { + "colwidths": [100], + "side_left": False, + "side_right": False, + "footer": False, + }, }, "simple_footer": { "func": self._grid_simple, - "configs": {"colwidths": [100], "side_left": False, "side_right": False, "footer": True}, + "configs": { + "colwidths": [100], + "side_left": False, + "side_right": False, + "footer": True, + }, }, "simple_side_left": { "func": self._grid_simple, - "configs": {"colwidths": [30, 70], "side_left": "full", "side_right": False, "footer": False}, + "configs": { + "colwidths": [30, 70], + "side_left": "full", + "side_right": False, + "footer": False, + }, }, "simple_side_right": { "func": self._grid_simple, - "configs": {"colwidths": [70, 30], "side_left": False, "side_right": "full", "footer": False}, + "configs": { + "colwidths": [70, 30], + "side_left": False, + "side_right": "full", + "footer": False, + }, }, "simple_side_left_partial": { "func": self._grid_simple, - "configs": {"colwidths": [20, 80], "side_left": "part", "side_right": False, "footer": False}, + "configs": { + "colwidths": [20, 80], + "side_left": "part", + "side_right": False, + "footer": False, + }, }, "simple_side_right_partial": { "func": self._grid_simple, - "configs": {"colwidths": [80, 20], "side_left": False, "side_right": "part", "footer": False}, + "configs": { + "colwidths": [80, 20], + "side_left": False, + "side_right": "part", + "footer": False, + }, }, "complex": self._grid_complex, "content": { "func": self._grid_content, - "configs": {"colwidths": [100], "side_left": False, "side_right": False, "footer": False}, + "configs": { + "colwidths": [100], + "side_left": False, + "side_right": False, + "footer": False, + }, }, "content_footer": { "func": self._grid_content, - "configs": {"colwidths": [100], "side_left": False, "side_right": False, "footer": True}, + "configs": { + "colwidths": [100], + "side_left": False, + "side_right": False, + "footer": True, + }, }, "content_side_left": { "func": self._grid_content, - "configs": {"colwidths": [5, 95], "side_left": True, "side_right": False, "footer": False}, + "configs": { + "colwidths": [5, 95], + "side_left": True, + "side_right": False, + "footer": False, + }, }, "content_side_right": { "func": self._grid_content, - "configs": {"colwidths": [95, 5], "side_left": False, "side_right": True, "footer": False}, + "configs": { + "colwidths": [95, 5], + "side_left": False, + "side_right": True, + "footer": False, + }, }, "content_footer_side_left": { "func": self._grid_content, - "configs": {"colwidths": [5, 95], "side_left": True, "side_right": False, "footer": True}, + "configs": { + "colwidths": [5, 95], + "side_left": True, + "side_right": False, + "footer": True, + }, }, "content_footer_side_right": { "func": self._grid_content, - "configs": {"colwidths": [95, 5], "side_left": False, "side_right": True, "footer": True}, + "configs": { + "colwidths": [95, 5], + "side_left": False, + "side_right": True, + "footer": True, + }, }, } # Dummy Document setup self.doc_settings, self.inline_parser = _generate_inline_parser() self.dummy_doc = new_document("dummy", self.doc_settings) - self.doc_language = languages.get_language(self.dummy_doc.settings.language_code) + self.doc_language = languages.get_language( + self.dummy_doc.settings.language_code + ) self.doc_memo = Struct( document=self.dummy_doc, reporter=self.dummy_doc.reporter, @@ -304,7 +382,9 @@ def __init__( inliner=None, ) - self.functions: dict[str, Callable[..., None | nodes.Node | list[nodes.Node]]] = { + self.functions: dict[ + str, Callable[..., None | nodes.Node | list[nodes.Node]] + ] = { "meta": self.meta, # type: ignore[dict-item] "meta_all": self.meta_all, "meta_links": self.meta_links, @@ -334,7 +414,9 @@ def __init__( def get_need_table(self) -> nodes.table: if self.layout["grid"] not in self.grids.keys(): raise SphinxNeedLayoutException( - "Unknown layout-grid: {}. Supported are {}".format(self.layout["grid"], ", ".join(self.grids.keys())) + "Unknown layout-grid: {}. Supported are {}".format( + self.layout["grid"], ", ".join(self.grids.keys()) + ) ) func = self.grids[self.layout["grid"]] @@ -376,7 +458,9 @@ def _parse(self, line: str) -> list[nodes.Node]: :param line: string to parse :return: nodes """ - result, message = self.inline_parser.parse(line, 0, self.doc_memo, self.dummy_doc) # type: ignore + result, message = self.inline_parser.parse( # type: ignore + line, 0, self.doc_memo, self.dummy_doc + ) if message: raise SphinxNeedLayoutException(message) return result # type: ignore[no-any-return] @@ -420,7 +504,9 @@ def _func_replace(self, section_nodes: list[nodes.Node]) -> list[nodes.Node]: ) func_def_clean = func_def.replace("<<", "").replace(">>", "") - func_name, func_args, func_kargs = _analyze_func_string(func_def_clean, None) + func_name, func_args, func_kargs = _analyze_func_string( + func_def_clean, None + ) # Replace place holders # Looks for {{name}}, where name must be an option of need, and replaces it with the @@ -552,7 +638,9 @@ def meta( ref_item = nodes.Text(datum) data_node += ref_item - if (name in needs_string_links_option and index + 1 < len(data)) or index + 1 < len([data]): + if ( + name in needs_string_links_option and index + 1 < len(data) + ) or index + 1 < len([data]): data_node += nodes.emphasis("; ", "; ") data_container.append(data_node) @@ -703,7 +791,9 @@ def meta_links(self, name: str, incoming: bool = False) -> nodes.inline: data_container.append(node_links) return data_container - def meta_links_all(self, prefix: str = "", postfix: str = "", exclude: list[str] | None = None) -> list[nodes.line]: + def meta_links_all( + self, prefix: str = "", postfix: str = "", exclude: list[str] | None = None + ) -> list[nodes.line]: """ Documents all used link types for the current need automatically. @@ -718,7 +808,9 @@ def meta_links_all(self, prefix: str = "", postfix: str = "", exclude: list[str] type_key = link_type["option"] if self.need[type_key] and type_key not in exclude: # type: ignore[literal-required] outgoing_line = nodes.line() - outgoing_label = prefix + "{}:".format(link_type["outgoing"]) + postfix + " " + outgoing_label = ( + prefix + "{}:".format(link_type["outgoing"]) + postfix + " " + ) outgoing_line += self._parse(outgoing_label) outgoing_line += self.meta_links(link_type["option"], incoming=False) data_container.append(outgoing_line) @@ -726,7 +818,9 @@ def meta_links_all(self, prefix: str = "", postfix: str = "", exclude: list[str] type_key = link_type["option"] + "_back" if self.need[type_key] and type_key not in exclude: # type: ignore[literal-required] incoming_line = nodes.line() - incoming_label = prefix + "{}:".format(link_type["incoming"]) + postfix + " " + incoming_label = ( + prefix + "{}:".format(link_type["incoming"]) + postfix + " " + ) incoming_line += self._parse(incoming_label) incoming_line += self.meta_links(link_type["option"], incoming=True) data_container.append(incoming_line) @@ -791,7 +885,9 @@ def image( options["align"] = align if url is None or not isinstance(url, str): - raise SphinxNeedLayoutException("not valid url given for image function in layout") + raise SphinxNeedLayoutException( + "not valid url given for image function in layout" + ) if url.startswith("icon:"): if any(x in builder.name.upper() for x in ["PDF", "LATEX"]): @@ -926,7 +1022,11 @@ def link( return data_container def collapse_button( - self, target: str = "meta", collapsed: str = "Show", visible: str = "Close", initial: bool = False + self, + target: str = "meta", + collapsed: str = "Show", + visible: str = "Close", + initial: bool = False, ) -> nodes.inline | None: """ To show icons instead of text on the button, use collapse_button() like this:: @@ -952,16 +1052,28 @@ def collapse_button( if collapsed.startswith("image:") or collapsed.startswith("icon:"): coll_node_collapsed.append( - self.image(collapsed.replace("image:", ""), width="17px", no_link=True, img_class="sn_collapse_img") + self.image( + collapsed.replace("image:", ""), + width="17px", + no_link=True, + img_class="sn_collapse_img", + ) ) elif collapsed.startswith("Debug view"): - coll_node_collapsed.append(nodes.container(classes=["debug_on_layout_btn"])) # For debug layout + coll_node_collapsed.append( + nodes.container(classes=["debug_on_layout_btn"]) + ) # For debug layout else: coll_node_collapsed.append(nodes.Text(collapsed)) if visible.startswith("image:") or visible.startswith("icon:"): coll_node_visible.append( - self.image(visible.replace("image:", ""), width="17px", no_link=True, img_class="sn_collapse_img") + self.image( + visible.replace("image:", ""), + width="17px", + no_link=True, + img_class="sn_collapse_img", + ) ) elif visible.startswith("Debug view"): coll_node_visible.append(nodes.container(classes=["debug_off_layout_btn"])) @@ -972,7 +1084,9 @@ def collapse_button( # docutils doesn't allow has to add any html-attributes beside class and id to nodes. # So we misused "id" for this and use "__" (2x _) as separator for row-target names - if (not self.need["collapse"]) or (self.need["collapse"] is None and not initial): + if (not self.need["collapse"]) or ( + self.need["collapse"] is None and not initial + ): status = "show" if (self.need["collapse"]) or (not self.need["collapse"] and initial): @@ -1034,7 +1148,13 @@ def permalink( prefix=prefix, ) - def _grid_simple(self, colwidths: list[int], side_left: bool | str, side_right: bool | str, footer: bool) -> None: + def _grid_simple( + self, + colwidths: list[int], + side_left: bool | str, + side_right: bool | str, + footer: bool, + ) -> None: """ Creates most "simple" grid layouts. Side parts and footer can be activated via config. @@ -1104,7 +1224,9 @@ def _grid_simple(self, colwidths: list[int], side_left: bool | str, side_right: head_row = nodes.row(classes=["need", "head"]) if side_left: - side_entry = nodes.entry(classes=["need", "side"], morerows=side_left_morerows) + side_entry = nodes.entry( + classes=["need", "side"], morerows=side_left_morerows + ) side_entry += self.get_section("side") head_row += side_entry @@ -1113,7 +1235,9 @@ def _grid_simple(self, colwidths: list[int], side_left: bool | str, side_right: head_row += head_entry if side_right: - side_entry = nodes.entry(classes=["need", "side"], morerows=side_right_morerows) + side_entry = nodes.entry( + classes=["need", "side"], morerows=side_right_morerows + ) side_entry += self.get_section("side") head_row += side_entry @@ -1125,14 +1249,18 @@ def _grid_simple(self, colwidths: list[int], side_left: bool | str, side_right: # CONTENT row content_row = nodes.row(classes=["need", "content"]) - content_entry = nodes.entry(classes=["need", "content"], morecols=common_more_cols) + content_entry = nodes.entry( + classes=["need", "content"], morecols=common_more_cols + ) content_entry.insert(0, self.node.children) content_row += content_entry # FOOTER row if footer: footer_row = nodes.row(classes=["need", "footer"]) - footer_entry = nodes.entry(classes=["need", "footer"], morecols=common_more_cols) + footer_entry = nodes.entry( + classes=["need", "footer"], morecols=common_more_cols + ) footer_entry += self.get_section("footer") footer_row += footer_entry @@ -1207,7 +1335,9 @@ def _grid_complex(self) -> None: # Construct table node_tgroup += self.node_tbody - def _grid_content(self, colwidths: list[int], side_left: bool, side_right: bool, footer: bool) -> None: + def _grid_content( + self, colwidths: list[int], side_left: bool, side_right: bool, footer: bool + ) -> None: """ Creates most "content" based grid layouts. Side parts and footer can be activated via config. diff --git a/sphinx_needs/need_constraints.py b/sphinx_needs/need_constraints.py index e068a6bdf..b1925ab8a 100644 --- a/sphinx_needs/need_constraints.py +++ b/sphinx_needs/need_constraints.py @@ -11,7 +11,9 @@ logger = get_logger(__name__) -def process_constraints(needs: dict[str, NeedsInfoType], config: NeedsSphinxConfig) -> None: +def process_constraints( + needs: dict[str, NeedsInfoType], config: NeedsSphinxConfig +) -> None: """Analyse constraints of all needs, and set corresponding fields on the need data item: ``constraints_passed`` and ``constraints_results``. @@ -56,7 +58,9 @@ def process_constraints(needs: dict[str, NeedsInfoType], config: NeedsSphinxConf if "error_message" in executable_constraints: msg = str(executable_constraints["error_message"]) - template = error_templates_cache.setdefault(msg, jinja2.Template(msg)) + template = error_templates_cache.setdefault( + msg, jinja2.Template(msg) + ) need["constraints_error"] = template.render(**need) if "severity" not in executable_constraints: @@ -88,10 +92,14 @@ def process_constraints(needs: dict[str, NeedsInfoType], config: NeedsSphinxConf # set styles old_style = need["style"] if old_style and len(old_style) > 0: - new_styles = "".join(", " + x for x in failed_options.get("style", [])) + new_styles = "".join( + ", " + x for x in failed_options.get("style", []) + ) else: old_style = "" - new_styles = "".join(x + "," for x in failed_options.get("style", [])) + new_styles = "".join( + x + "," for x in failed_options.get("style", []) + ) if failed_options.get("force_style", False): need["style"] = new_styles.strip(", ") diff --git a/sphinx_needs/needs.py b/sphinx_needs/needs.py index e252dfc7f..4d99df291 100644 --- a/sphinx_needs/needs.py +++ b/sphinx_needs/needs.py @@ -109,7 +109,10 @@ __version__ = VERSION = "2.0.0" NEEDS_FUNCTIONS.clear() -_NODE_TYPES_T = Dict[Type[nodes.Element], Callable[[Sphinx, nodes.document, str, List[nodes.Element]], None]] +_NODE_TYPES_T = Dict[ + Type[nodes.Element], + Callable[[Sphinx, nodes.document, str, List[nodes.Element]], None], +] NODE_TYPES_PRIO: _NODE_TYPES_T = { # Node types to be checked before most others Needextract: process_needextract, @@ -150,7 +153,9 @@ def setup(app: Sphinx) -> dict[str, Any]: NeedsSphinxConfig.add_config_values(app) # Define nodes - app.add_node(Need, html=(html_visit, html_depart), latex=(latex_visit, latex_depart)) + app.add_node( + Need, html=(html_visit, html_depart), latex=(latex_visit, latex_depart) + ) app.add_node( Needfilter, ) @@ -167,7 +172,11 @@ def setup(app: Sphinx) -> dict[str, Any]: app.add_node(Needextend) app.add_node(Needuml) app.add_node(List2Need) - app.add_node(NeedPart, html=(visitor_dummy, visitor_dummy), latex=(visitor_dummy, visitor_dummy)) + app.add_node( + NeedPart, + html=(visitor_dummy, visitor_dummy), + latex=(visitor_dummy, visitor_dummy), + ) ######################################################################## # DIRECTIVES @@ -195,23 +204,54 @@ def setup(app: Sphinx) -> dict[str, Any]: # ROLES ######################################################################## # Provides :need:`ABC_123` for inline links. - app.add_role("need", NeedsXRefRole(nodeclass=NeedRef, innernodeclass=nodes.emphasis, warn_dangling=True)) + app.add_role( + "need", + NeedsXRefRole( + nodeclass=NeedRef, innernodeclass=nodes.emphasis, warn_dangling=True + ), + ) app.add_role( - "need_incoming", NeedsXRefRole(nodeclass=NeedIncoming, innernodeclass=nodes.emphasis, warn_dangling=True) + "need_incoming", + NeedsXRefRole( + nodeclass=NeedIncoming, innernodeclass=nodes.emphasis, warn_dangling=True + ), ) app.add_role( - "need_outgoing", NeedsXRefRole(nodeclass=NeedOutgoing, innernodeclass=nodes.emphasis, warn_dangling=True) + "need_outgoing", + NeedsXRefRole( + nodeclass=NeedOutgoing, innernodeclass=nodes.emphasis, warn_dangling=True + ), ) - app.add_role("need_part", NeedsXRefRole(nodeclass=NeedPart, innernodeclass=nodes.inline, warn_dangling=True)) + app.add_role( + "need_part", + NeedsXRefRole( + nodeclass=NeedPart, innernodeclass=nodes.inline, warn_dangling=True + ), + ) # Shortcut for need_part - app.add_role("np", NeedsXRefRole(nodeclass=NeedPart, innernodeclass=nodes.inline, warn_dangling=True)) + app.add_role( + "np", + NeedsXRefRole( + nodeclass=NeedPart, innernodeclass=nodes.inline, warn_dangling=True + ), + ) - app.add_role("need_count", NeedsXRefRole(nodeclass=NeedCount, innernodeclass=nodes.inline, warn_dangling=True)) + app.add_role( + "need_count", + NeedsXRefRole( + nodeclass=NeedCount, innernodeclass=nodes.inline, warn_dangling=True + ), + ) - app.add_role("need_func", NeedsXRefRole(nodeclass=NeedFunc, innernodeclass=nodes.inline, warn_dangling=True)) + app.add_role( + "need_func", + NeedsXRefRole( + nodeclass=NeedFunc, innernodeclass=nodes.inline, warn_dangling=True + ), + ) ######################################################################## # EVENTS @@ -241,7 +281,11 @@ def setup(app: Sphinx) -> dict[str, Any]: # doctree-read. So manipulating the doctree may result in conflicts, as e.g. images get not # registered for sphinx. So some sphinx-internal tasks/functions may be called by hand again... # See also https://github.com/sphinx-doc/sphinx/issues/7054#issuecomment-578019701 for an example - app.connect("doctree-resolved", process_creator(NODE_TYPES_PRIO, "needextract"), priority=100) + app.connect( + "doctree-resolved", + process_creator(NODE_TYPES_PRIO, "needextract"), + priority=100, + ) app.connect("doctree-resolved", process_need_nodes) app.connect("doctree-resolved", process_creator(NODE_TYPES)) @@ -280,7 +324,8 @@ def process_caller(app: Sphinx, doctree: nodes.document, fromdocname: str) -> No """ # We only need to analyse docs, which have Sphinx-Needs directives in it. if ( - fromdocname not in SphinxNeedsData(app.env).get_or_create_docs().get(doc_category, []) + fromdocname + not in SphinxNeedsData(app.env).get_or_create_docs().get(doc_category, []) and fromdocname != f"{app.config.root_doc}" ): return @@ -297,7 +342,11 @@ def process_caller(app: Sphinx, doctree: nodes.document, fromdocname: str) -> No # Let's call the handlers for check_node, check_func in node_list.items(): # Call the handler only, if it defined, and we found some nodes for it - if check_node in current_nodes and check_func is not None and current_nodes[check_node]: + if ( + check_node in current_nodes + and check_func is not None + and current_nodes[check_node] + ): check_func(app, doctree, fromdocname, current_nodes[check_node]) return process_caller @@ -319,7 +368,9 @@ def load_config(app: Sphinx, *_args: Any) -> None: for option in needs_config.extra_options: if option in extra_options: LOGGER.warning( - f'extra_option "{option}" already registered. [needs.config]', type="needs", subtype="config" + f'extra_option "{option}" already registered. [needs.config]', + type="needs", + subtype="config", ) NEEDS_CONFIG.extra_options[option] = directives.unchanged @@ -397,7 +448,9 @@ def load_config(app: Sphinx, *_args: Any) -> None: NEEDS_CONFIG.warnings[name] = check else: LOGGER.warning( - f"{name!r} in 'needs_warnings' is already registered. [needs.config]", type="needs", subtype="config" + f"{name!r} in 'needs_warnings' is already registered. [needs.config]", + type="needs", + subtype="config", ) if needs_config.constraints_failed_color: @@ -441,7 +494,11 @@ def prepare_env(app: Sphinx, env: BuildEnvironment, _docname: str) -> None: # Register user defined services for name, service in needs_config.services.items(): - if name not in services.services and "class" in service and "class_init" in service: + if ( + name not in services.services + and "class" in service + and "class_init" in service + ): # We found a not yet registered service # But only register, if service-config contains class and class_init. # Otherwise, the service may get registered later by an external sphinx-needs extension @@ -456,7 +513,14 @@ def prepare_env(app: Sphinx, env: BuildEnvironment, _docname: str) -> None: register_func(needs_func) # Own extra options - for option in ["hidden", "duration", "completion", "has_dead_links", "has_forbidden_dead_links", "constraints"]: + for option in [ + "hidden", + "duration", + "completion", + "has_dead_links", + "has_forbidden_dead_links", + "constraints", + ]: # Check if not already set by user if option not in NEEDS_CONFIG.extra_options: NEEDS_CONFIG.extra_options[option] = directives.unchanged @@ -525,25 +589,29 @@ def check_configuration(_app: Sphinx, config: Config) -> None: # Check if needs external filter and extra option are using the same name if extern_filter in extra_options: raise NeedsConfigException( - "Same name for external filter and extra option: {}." " This is not allowed.".format(extern_filter) + f"Same name for external filter and extra option: {extern_filter}." + " This is not allowed." ) # Check for usage of internal names for internal in INTERNALS: if internal in extra_options: raise NeedsConfigException( - 'Extra option "{}" already used internally. ' " Please use another name.".format(internal) + f'Extra option "{internal}" already used internally. ' + " Please use another name." ) if internal in link_types: raise NeedsConfigException( - 'Link type name "{}" already used internally. ' " Please use another name.".format(internal) + f'Link type name "{internal}" already used internally. ' + " Please use another name." ) # Check if option and link are using the same name for link in link_types: if link in extra_options: raise NeedsConfigException( - "Same name for link type and extra option: {}." " This is not allowed.".format(link) + f"Same name for link type and extra option: {link}." + " This is not allowed." ) if link + "_back" in extra_options: raise NeedsConfigException( @@ -562,7 +630,11 @@ def check_configuration(_app: Sphinx, config: Config) -> None: for option in external_variant_options: # Check variant option is added in either extra options or extra links or NEED_DEFAULT_OPTIONS - if option not in extra_options and option not in link_types and option not in NEED_DEFAULT_OPTIONS.keys(): + if ( + option not in extra_options + and option not in link_types + and option not in NEED_DEFAULT_OPTIONS.keys() + ): raise NeedsConfigException( "Variant option `{}` is not added in either extra options or extra links. " "This is not allowed.".format(option) diff --git a/sphinx_needs/needsfile.py b/sphinx_needs/needsfile.py index ece2bbd66..cf1184fc8 100644 --- a/sphinx_needs/needsfile.py +++ b/sphinx_needs/needsfile.py @@ -94,16 +94,30 @@ def update_or_add_version(self, version: str) -> None: def add_need(self, version: str, need_info: NeedsInfoType) -> None: self.update_or_add_version(version) - writable_needs = {key: need_info[key] for key in need_info if key not in self._exclude_need_keys} # type: ignore[literal-required] + writable_needs = { + key: need_info[key] # type: ignore[literal-required] + for key in need_info + if key not in self._exclude_need_keys + } writable_needs["description"] = need_info["content"] self.needs_list["versions"][version]["needs"][need_info["id"]] = writable_needs - self.needs_list["versions"][version]["needs_amount"] = len(self.needs_list["versions"][version]["needs"]) + self.needs_list["versions"][version]["needs_amount"] = len( + self.needs_list["versions"][version]["needs"] + ) def add_filter(self, version: str, need_filter: NeedsFilterType) -> None: self.update_or_add_version(version) - writable_filters = {key: need_filter[key] for key in need_filter if key not in self._exclude_filter_keys} # type: ignore[literal-required] - self.needs_list["versions"][version]["filters"][need_filter["export_id"].upper()] = writable_filters - self.needs_list["versions"][version]["filters_amount"] = len(self.needs_list["versions"][version]["filters"]) + writable_filters = { + key: need_filter[key] # type: ignore[literal-required] + for key in need_filter + if key not in self._exclude_filter_keys + } + self.needs_list["versions"][version]["filters"][ + need_filter["export_id"].upper() + ] = writable_filters + self.needs_list["versions"][version]["filters_amount"] = len( + self.needs_list["versions"][version]["filters"] + ) def wipe_version(self, version: str) -> None: if version in self.needs_list["versions"]: @@ -130,7 +144,9 @@ def load_json(self, file: str) -> None: file = os.path.join(self.confdir, file) if not os.path.exists(file): - self.log.warning(f"Could not load needs json file {file} [needs]", type="needs") + self.log.warning( + f"Could not load needs json file {file} [needs]", type="needs" + ) else: errors = check_needs_file(file) # We only care for schema errors here, all other possible errors @@ -144,7 +160,9 @@ def load_json(self, file: str) -> None: try: needs_list = json.load(needs_file) except json.JSONDecodeError: - self.log.warning(f"Could not decode json file {file} [needs]", type="needs") + self.log.warning( + f"Could not decode json file {file} [needs]", type="needs" + ) else: self.needs_list = needs_list diff --git a/sphinx_needs/roles/need_count.py b/sphinx_needs/roles/need_count.py index 8ff1299a8..15275a090 100644 --- a/sphinx_needs/roles/need_count.py +++ b/sphinx_needs/roles/need_count.py @@ -23,7 +23,10 @@ class NeedCount(nodes.Inline, nodes.Element): def process_need_count( - app: Sphinx, doctree: nodes.document, _fromdocname: str, found_nodes: list[nodes.Element] + app: Sphinx, + doctree: nodes.document, + _fromdocname: str, + found_nodes: list[nodes.Element], ) -> None: needs_config = NeedsSphinxConfig(app.config) for node_need_count in found_nodes: diff --git a/sphinx_needs/roles/need_func.py b/sphinx_needs/roles/need_func.py index 23daee4ac..3497f395b 100644 --- a/sphinx_needs/roles/need_func.py +++ b/sphinx_needs/roles/need_func.py @@ -18,11 +18,18 @@ class NeedFunc(nodes.Inline, nodes.Element): def process_need_func( - app: Sphinx, doctree: nodes.document, _fromdocname: str, found_nodes: list[nodes.Element] + app: Sphinx, + doctree: nodes.document, + _fromdocname: str, + found_nodes: list[nodes.Element], ) -> None: env = app.env # for node_need_func in doctree.findall(NeedFunc): for node_need_func in found_nodes: - result = check_and_get_content(node_need_func.attributes["reftarget"], {"id": "need_func_dummy"}, env) # type: ignore + result = check_and_get_content( + node_need_func.attributes["reftarget"], + {"id": "need_func_dummy"}, # type: ignore + env, + ) new_node_func = nodes.Text(str(result)) node_need_func.replace_self(new_node_func) diff --git a/sphinx_needs/roles/need_incoming.py b/sphinx_needs/roles/need_incoming.py index fcdf5251b..2aa939035 100644 --- a/sphinx_needs/roles/need_incoming.py +++ b/sphinx_needs/roles/need_incoming.py @@ -15,7 +15,10 @@ class NeedIncoming(nodes.Inline, nodes.Element): def process_need_incoming( - app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element] + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], ) -> None: builder = app.builder env = app.env @@ -64,8 +67,12 @@ def process_need_incoming( node_need_backref["reftarget"], ) else: - assert target_need["external_url"] is not None, "External URL must not be set" - new_node_ref = nodes.reference(target_need["id"], target_need["id"]) + assert ( + target_need["external_url"] is not None + ), "External URL must not be set" + new_node_ref = nodes.reference( + target_need["id"], target_need["id"] + ) new_node_ref["refuri"] = check_and_calc_base_url_rel_path( target_need["external_url"], fromdocname ) @@ -82,7 +89,10 @@ def process_need_incoming( pass else: - logger.warning(f"need {node_need_backref['reftarget']} not found [needs]", location=node_need_backref) + logger.warning( + f"need {node_need_backref['reftarget']} not found [needs]", + location=node_need_backref, + ) if len(node_link_container.children) == 0: node_link_container += nodes.Text("None") diff --git a/sphinx_needs/roles/need_outgoing.py b/sphinx_needs/roles/need_outgoing.py index 1939b7e4e..c6391129d 100644 --- a/sphinx_needs/roles/need_outgoing.py +++ b/sphinx_needs/roles/need_outgoing.py @@ -18,7 +18,10 @@ class NeedOutgoing(nodes.Inline, nodes.Element): def process_need_outgoing( - app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element] + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], ) -> None: builder = app.builder env = app.env @@ -55,7 +58,11 @@ def process_need_outgoing( target_need = needs_all_needs[need_id_main] if need_id_part and need_id_part in target_need["parts"]: part_content = target_need["parts"][need_id_part]["content"] - target_title = part_content if len(part_content) < 30 else part_content[:27] + "..." + target_title = ( + part_content + if len(part_content) < 30 + else part_content[:27] + "..." + ) target_id = ".".join([need_id_main, need_id_part]) else: target_title = target_need["title"] @@ -84,8 +91,12 @@ def process_need_outgoing( node_need_ref["reftarget"], ) else: - assert target_need["external_url"] is not None, "External URL must be set" - new_node_ref = nodes.reference(target_need["id"], target_need["id"]) + assert ( + target_need["external_url"] is not None + ), "External URL must be set" + new_node_ref = nodes.reference( + target_need["id"], target_need["id"] + ) new_node_ref["refuri"] = check_and_calc_base_url_rel_path( target_need["external_url"], fromdocname ) diff --git a/sphinx_needs/roles/need_part.py b/sphinx_needs/roles/need_part.py index 242d197d4..ae2b1eb89 100644 --- a/sphinx_needs/roles/need_part.py +++ b/sphinx_needs/roles/need_part.py @@ -27,14 +27,21 @@ class NeedPart(nodes.Inline, nodes.Element): pass -def process_need_part(app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element]) -> None: +def process_need_part( + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], +) -> None: pass part_pattern = re.compile(r"\(([\w-]+)\)(.*)") -def update_need_with_parts(env: BuildEnvironment, need: NeedsInfoType, part_nodes: list[NeedPart]) -> None: +def update_need_with_parts( + env: BuildEnvironment, need: NeedsInfoType, part_nodes: list[NeedPart] +) -> None: app = env.app builder = app.builder for part_node in part_nodes: @@ -45,7 +52,9 @@ def update_need_with_parts(env: BuildEnvironment, need: NeedsInfoType, part_node part_content = result.group(2) else: part_content = content - inline_id = hashlib.sha1(part_content.encode("UTF-8")).hexdigest().upper()[:3] + inline_id = ( + hashlib.sha1(part_content.encode("UTF-8")).hexdigest().upper()[:3] + ) if "parts" not in need: need["parts"] = {} @@ -78,7 +87,9 @@ def update_need_with_parts(env: BuildEnvironment, need: NeedsInfoType, part_node from sphinx.util.nodes import make_refnode - part_ref_node = make_refnode(builder, need["docname"], need["docname"], part_id_ref, part_link_node) + part_ref_node = make_refnode( + builder, need["docname"], need["docname"], part_id_ref, part_link_node + ) part_ref_node["classes"] += ["needs-id"] part_node.children = [] diff --git a/sphinx_needs/roles/need_ref.py b/sphinx_needs/roles/need_ref.py index d817b9274..231d3c627 100644 --- a/sphinx_needs/roles/need_ref.py +++ b/sphinx_needs/roles/need_ref.py @@ -51,7 +51,12 @@ def transform_need_to_dict(need: NeedsInfoType) -> dict[str, str]: return dict_need -def process_need_ref(app: Sphinx, doctree: nodes.document, fromdocname: str, found_nodes: list[nodes.Element]) -> None: +def process_need_ref( + app: Sphinx, + doctree: nodes.document, + fromdocname: str, + found_nodes: list[nodes.Element], +) -> None: builder = app.builder env = app.env needs_config = NeedsSphinxConfig(env.config) @@ -78,7 +83,9 @@ def process_need_ref(app: Sphinx, doctree: nodes.document, fromdocname: str, fou if need_id_main in all_needs: target_need = all_needs[need_id_main] - dict_need = transform_need_to_dict(target_need) # Transform a dict in a dict of {str, str} + dict_need = transform_need_to_dict( + target_need + ) # Transform a dict in a dict of {str, str} # We set the id to the complete id maintained in node_need_ref["reftarget"] dict_need["id"] = need_id_full @@ -118,7 +125,8 @@ def process_need_ref(app: Sphinx, doctree: nodes.document, fromdocname: str, fou link_text = needs_config.role_need_template.format(**dict_need) except KeyError as e: link_text = ( - '"the config parameter needs_role_need_template uses not supported placeholders: %s "' % e + '"the config parameter needs_role_need_template uses not supported placeholders: %s "' + % e ) log.warning(link_text + " [needs]", type="needs") @@ -135,9 +143,13 @@ def process_need_ref(app: Sphinx, doctree: nodes.document, fromdocname: str, fou node_need_ref["reftarget"], ) else: - assert target_need["external_url"] is not None, "external_url must be set for external needs" + assert ( + target_need["external_url"] is not None + ), "external_url must be set for external needs" new_node_ref = nodes.reference(target_need["id"], target_need["id"]) - new_node_ref["refuri"] = check_and_calc_base_url_rel_path(target_need["external_url"], fromdocname) + new_node_ref["refuri"] = check_and_calc_base_url_rel_path( + target_need["external_url"], fromdocname + ) new_node_ref["classes"].append(target_need["external_css"]) else: diff --git a/sphinx_needs/services/config/github.py b/sphinx_needs/services/config/github.py index ed2c2a6e2..65f40708c 100644 --- a/sphinx_needs/services/config/github.py +++ b/sphinx_needs/services/config/github.py @@ -3,9 +3,22 @@ EXTRA_DATA_OPTIONS = ["user", "created_at", "updated_at", "closed_at", "service"] EXTRA_LINK_OPTIONS = ["url"] EXTRA_IMAGE_OPTIONS = ["avatar"] -CONFIG_OPTIONS = ["type", "query", "specific", "max_amount", "max_content_lines", "id_prefix"] -GITHUB_DATA = ["status", "tags"] + EXTRA_DATA_OPTIONS + EXTRA_LINK_OPTIONS + EXTRA_IMAGE_OPTIONS -GITHUB_DATA_STR = '"' + '","'.join(EXTRA_DATA_OPTIONS + EXTRA_LINK_OPTIONS + EXTRA_IMAGE_OPTIONS) + '"' +CONFIG_OPTIONS = [ + "type", + "query", + "specific", + "max_amount", + "max_content_lines", + "id_prefix", +] +GITHUB_DATA = ( + ["status", "tags"] + EXTRA_DATA_OPTIONS + EXTRA_LINK_OPTIONS + EXTRA_IMAGE_OPTIONS +) +GITHUB_DATA_STR = ( + '"' + + '","'.join(EXTRA_DATA_OPTIONS + EXTRA_LINK_OPTIONS + EXTRA_IMAGE_OPTIONS) + + '"' +) CONFIG_DATA_STR = '"' + '","'.join(CONFIG_OPTIONS) + '"' GITHUB_LAYOUT = { "grid": "complex", @@ -18,14 +31,20 @@ "head": [ '**<>** (' + ", ".join( - ['<>'.format(value=x) for x in EXTRA_LINK_OPTIONS] + [ + f'<>' + for x in EXTRA_LINK_OPTIONS + ] ) + ")" ], - "head_right": ['<>', '<>'], - "meta_left": ['<>'.format(value=x) for x in EXTRA_DATA_OPTIONS] + "head_right": [ + '<>', + '<>', + ], + "meta_left": [f'<>' for x in EXTRA_DATA_OPTIONS] + [ - '<>'.format(value=x) + f'<>' for x in EXTRA_LINK_OPTIONS ], "meta_right": [ diff --git a/sphinx_needs/services/github.py b/sphinx_needs/services/github.py index b2fc6da72..4e5c54c84 100644 --- a/sphinx_needs/services/github.py +++ b/sphinx_needs/services/github.py @@ -25,9 +25,13 @@ class GithubService(BaseService): - options = CONFIG_OPTIONS + EXTRA_DATA_OPTIONS + EXTRA_LINK_OPTIONS + EXTRA_IMAGE_OPTIONS + options = ( + CONFIG_OPTIONS + EXTRA_DATA_OPTIONS + EXTRA_LINK_OPTIONS + EXTRA_IMAGE_OPTIONS + ) - def __init__(self, app: Sphinx, name: str, config: dict[str, Any], **kwargs: Any) -> None: + def __init__( + self, app: Sphinx, name: str, config: dict[str, Any], **kwargs: Any + ) -> None: self.app = app self.name = name self.config = config @@ -50,7 +54,11 @@ def __init__(self, app: Sphinx, name: str, config: dict[str, Any], **kwargs: Any layouts["github"] = GITHUB_LAYOUT self.gh_type_config = { - "issue": {"url": "search/issues", "query": "is:issue", "need_type": "issue"}, + "issue": { + "url": "search/issues", + "query": "is:issue", + "need_type": "issue", + }, "pr": {"url": "search/issues", "query": "is:pr", "need_type": "pr"}, "commit": {"url": "search/commits", "query": "", "need_type": "commit"}, } @@ -68,15 +76,21 @@ def __init__(self, app: Sphinx, name: str, config: dict[str, Any], **kwargs: Any if self.gh_type not in self.gh_type_config.keys(): raise KeyError( - 'github type "{}" not supported. Use: {}'.format(self.gh_type, ", ".join(self.gh_type_config.keys())) + 'github type "{}" not supported. Use: {}'.format( + self.gh_type, ", ".join(self.gh_type_config.keys()) + ) ) # Set need_type to use by default - self.need_type = self.config.get("need_type", self.gh_type_config[self.gh_type]["need_type"]) + self.need_type = self.config.get( + "need_type", self.gh_type_config[self.gh_type]["need_type"] + ) super().__init__() - def _send(self, query: str, options: dict[str, Any], specific: bool = False) -> dict[str, Any]: + def _send( + self, query: str, options: dict[str, Any], specific: bool = False + ) -> dict[str, Any]: headers = {} if self.gh_type == "commit": headers["Accept"] = "application/vnd.github.cloak-preview+json" @@ -93,17 +107,20 @@ def _send(self, query: str, options: dict[str, Any], specific: bool = False) -> single_type = "pulls" else: single_type = "commits" - url = self.url + "repos/{owner}/{repo}/{single_type}/{number}".format( - owner=owner, repo=repo, single_type=single_type, number=number - ) + url = self.url + f"repos/{owner}/{repo}/{single_type}/{number}" except IndexError: - raise NeedGithubServiceException('Single option ot valid, must follow "owner/repo/number"') + raise NeedGithubServiceException( + 'Single option ot valid, must follow "owner/repo/number"' + ) params = {} else: url = self.url + self.gh_type_config[self.gh_type]["url"] query = "{} {}".format(query, self.gh_type_config[self.gh_type]["query"]) - params = {"q": query, "per_page": options.get("max_amount", self.max_amount)} + params = { + "q": query, + "per_page": options.get("max_amount", self.max_amount), + } self.log.info(f"Service {self.name} requesting data for query: {query}") @@ -122,26 +139,30 @@ def _send(self, query: str, options: dict[str, Any], specific: bool = False) -> if "rate limit" in resp.json()["message"]: resp_limit = requests.get(self.url + "rate_limit", auth=auth) extra_info = resp_limit.json() - self.log.info("GitHub: API rate limit exceeded. We need to wait 60 secs...") + self.log.info( + "GitHub: API rate limit exceeded. We need to wait 60 secs..." + ) self.log.info(extra_info) time.sleep(61) resp = requests.get(url, params=params, auth=auth, headers=headers) if resp.status_code > 299: if "rate limit" in resp.json()["message"]: - raise NeedGithubServiceException("GitHub: API rate limit exceeded (twice). Stop here.") + raise NeedGithubServiceException( + "GitHub: API rate limit exceeded (twice). Stop here." + ) else: raise NeedGithubServiceException( "Github service error during request.\n" - "Status code: {}\n" - "Error: {}\n" - "{}".format(resp.status_code, resp.text, extra_info) + f"Status code: {resp.status_code}\n" + f"Error: {resp.text}\n" + f"{extra_info}" ) else: raise NeedGithubServiceException( "Github service error during request.\n" - "Status code: {}\n" - "Error: {}\n" - "{}".format(resp.status_code, resp.text, extra_info) + f"Status code: {resp.status_code}\n" + f"Error: {resp.text}\n" + f"{extra_info}" ) if specific: @@ -154,9 +175,13 @@ def request(self, options: dict[str, Any] | None = None) -> list[dict[str, Any]] self.log.debug(f"Requesting data for service {self.name}") if "query" not in options and "specific" not in options: - raise NeedGithubServiceException('"query" or "specific" missing as option for github service.') + raise NeedGithubServiceException( + '"query" or "specific" missing as option for github service.' + ) elif "query" in options and "specific" in options: - raise NeedGithubServiceException('Only "query" or "specific" allowed for github service. Not both!') + raise NeedGithubServiceException( + 'Only "query" or "specific" allowed for github service. Not both!' + ) elif "query" in options: query = options["query"] specific = False @@ -168,7 +193,9 @@ def request(self, options: dict[str, Any] | None = None) -> list[dict[str, Any]] if "items" not in response: if "errors" in response: raise NeedGithubServiceException( - "GitHub service query error: {}\n" "Used query: {}".format(response["errors"][0]["message"], query) + "GitHub service query error: {}\n" "Used query: {}".format( + response["errors"][0]["message"], query + ) ) else: raise NeedGithubServiceException("Github service: Unknown error.") @@ -182,7 +209,9 @@ def request(self, options: dict[str, Any] | None = None) -> list[dict[str, Any]] return data - def prepare_issue_data(self, items: list[dict[str, Any]], options: dict[str, Any]) -> list[dict[str, Any]]: + def prepare_issue_data( + self, items: list[dict[str, Any]], options: dict[str, Any] + ) -> list[dict[str, Any]]: data = [] for item in items: # ensure that "None" can not reach .splitlines() @@ -191,7 +220,11 @@ def prepare_issue_data(self, items: list[dict[str, Any]], options: dict[str, Any # wraps content lines, if they are too long. Respects already existing newlines. content_lines = [ - "\n ".join(textwrap.wrap(line, 60, break_long_words=True, replace_whitespace=False)) + "\n ".join( + textwrap.wrap( + line, 60, break_long_words=True, replace_whitespace=False + ) + ) for line in item["body"].splitlines() # type: ignore if line.strip() ] @@ -199,7 +232,9 @@ def prepare_issue_data(self, items: list[dict[str, Any]], options: dict[str, Any content = "\n\n ".join(content_lines) # Reduce content length, if requested by config if self.max_content_lines > 0: - max_lines = int(options.get("max_content_lines", self.max_content_lines)) + max_lines = int( + options.get("max_content_lines", self.max_content_lines) + ) content_lines = content.splitlines() if len(content_lines) > max_lines: content_lines = content_lines[0:max_lines] @@ -242,7 +277,9 @@ def prepare_issue_data(self, items: list[dict[str, Any]], options: dict[str, Any return data - def prepare_commit_data(self, items: list[dict[str, Any]], options: dict[str, Any]) -> list[dict[str, Any]]: + def prepare_commit_data( + self, items: list[dict[str, Any]], options: dict[str, Any] + ) -> list[dict[str, Any]]: data = [] for item in items: @@ -253,7 +290,9 @@ def prepare_commit_data(self, items: list[dict[str, Any]], options: dict[str, An "type": options.get("type", self.need_type), "layout": options.get("layout", self.layout), "id": self.id_prefix + item["sha"][:6], - "title": item["commit"]["message"].split("\n")[0][:60], # 1. line, max length 60 chars + "title": item["commit"]["message"].split("\n")[0][ + :60 + ], # 1. line, max length 60 chars "content": item["commit"]["message"], "user": item["author"]["login"], "url": item["html_url"], @@ -278,7 +317,9 @@ def _get_avatar(self, avatar_url: str) -> str: avatar_file_path = os.path.join(path, filename) # Placeholder avatar, if things go wrong or avatar download is deactivated - default_avatar_file_path = os.path.join(os.path.dirname(__file__), "../images/avatar.png") + default_avatar_file_path = os.path.join( + os.path.dirname(__file__), "../images/avatar.png" + ) if self.download_avatars: # Download only, if file not downloaded yet if not os.path.exists(avatar_file_path): @@ -294,20 +335,20 @@ def _get_avatar(self, avatar_url: str) -> str: f.write(response.content) elif response.status_code == 302: self.log.warning( - "GitHub service {} could not download avatar image " - "from {}.\n" - " Status code: {}\n" + f"GitHub service {self.name} could not download avatar image " + f"from {avatar_url}.\n" + f" Status code: {response.status_code}\n" " Reason: Looks like the authentication provider tries to redirect you." " This is not supported and is a common problem, " - "if you use GitHub Enterprise. [needs]".format(self.name, avatar_url, response.status_code), + "if you use GitHub Enterprise. [needs]", type="needs", ) avatar_file_path = default_avatar_file_path else: self.log.warning( - "GitHub service {} could not download avatar image " - "from {}.\n" - " Status code: {} [needs]".format(self.name, avatar_url, response.status_code), + f"GitHub service {self.name} could not download avatar image " + f"from {avatar_url}.\n" + f" Status code: {response.status_code} [needs]", type="needs", ) avatar_file_path = default_avatar_file_path @@ -316,7 +357,9 @@ def _get_avatar(self, avatar_url: str) -> str: return avatar_file_path - def _add_given_options(self, options: dict[str, Any], element_data: dict[str, Any]) -> None: + def _add_given_options( + self, options: dict[str, Any], element_data: dict[str, Any] + ) -> None: """ Add data from options, which was defined by user but is not set by this service diff --git a/sphinx_needs/services/manager.py b/sphinx_needs/services/manager.py index ecdacadaf..b95962a22 100644 --- a/sphinx_needs/services/manager.py +++ b/sphinx_needs/services/manager.py @@ -23,7 +23,9 @@ def register(self, name: str, klass: type[BaseService], **kwargs: Any) -> None: try: config = NeedsSphinxConfig(self.app.config).services[name] except KeyError: - self.log.debug(f"No service config found for {name}. Add it in your conf.py to needs_services dictionary.") + self.log.debug( + f"No service config found for {name}. Add it in your conf.py to needs_services dictionary." + ) config = {} # Register options from service class @@ -43,7 +45,9 @@ def get(self, name: str) -> BaseService: return self.services[name] else: raise NeedsServiceException( - "Service {} could not be found. " "Available services are {}".format(name, ", ".join(self.services)) + "Service {} could not be found. " "Available services are {}".format( + name, ", ".join(self.services) + ) ) diff --git a/sphinx_needs/services/open_needs.py b/sphinx_needs/services/open_needs.py index 6a9ea2195..d11e99b30 100644 --- a/sphinx_needs/services/open_needs.py +++ b/sphinx_needs/services/open_needs.py @@ -24,7 +24,9 @@ class OpenNeedsService(BaseService): options = CONFIG_OPTIONS + EXTRA_DATA_OPTIONS + EXTRA_LINK_OPTIONS - def __init__(self, app: Sphinx, name: str, config: dict[str, Any], **kwargs: Any) -> None: + def __init__( + self, app: Sphinx, name: str, config: dict[str, Any], **kwargs: Any + ) -> None: self.app = app self.name = name self.config = config @@ -41,7 +43,9 @@ def __init__(self, app: Sphinx, name: str, config: dict[str, Any], **kwargs: Any self.query = self.config.get("query", "") self.content = self.config.get("content", DEFAULT_CONTENT) self.mappings: dict[str, Any] = self.config.get("mappings", {}) - self.mapping_replaces = self.config.get("mappings_replaces", MAPPINGS_REPLACES_DEFAULT) + self.mapping_replaces = self.config.get( + "mappings_replaces", MAPPINGS_REPLACES_DEFAULT + ) self.extra_data: dict[str, Any] = self.config.get("extra_data", {}) self.params = self.config.get("params", "skip=0,limit=100") @@ -59,8 +63,8 @@ def _oauthorization(self) -> None: if login_resp.status_code != 200: raise OpenNeedsServiceException( "ONS service error during request.\n" - "Status code: {}\n" - "Error: {}\n".format(login_resp.status_code, login_resp.text) + f"Status code: {login_resp.status_code}\n" + f"Error: {login_resp.text}\n" ) oauth_credentials = dict(**login_resp.json()) self.token_type = oauth_credentials.get("token_type") @@ -72,8 +76,13 @@ def _prepare_request(self, options: Any) -> Any: url: str = options.get("url", self.url) url = url + str(self.url_postfix) - headers: dict[str, str] = {"Authorization": f"{self.token_type} {self.access_token}"} - params: list[str] = [param.strip() for param in re.split(r";|,", options.get("params", self.params))] + headers: dict[str, str] = { + "Authorization": f"{self.token_type} {self.access_token}" + } + params: list[str] = [ + param.strip() + for param in re.split(r";|,", options.get("params", self.params)) + ] new_params: str = "&".join(params) url = f"{url}?{new_params}" @@ -93,10 +102,14 @@ def _send_request(request: Any) -> Any: result: Any = requests.get(**request) if result.status_code >= 300: - raise OpenNeedsServiceException(f"Problem accessing {result.url}.\nReason: {result.text}") + raise OpenNeedsServiceException( + f"Problem accessing {result.url}.\nReason: {result.text}" + ) return result - def _extract_data(self, data: list[dict[str, Any]], options: dict[str, Any]) -> list[dict[str, Any]]: + def _extract_data( + self, data: list[dict[str, Any]], options: dict[str, Any] + ) -> list[dict[str, Any]]: """ Extract data of a list/dictionary, which was retrieved via send_request. :param data: list or dict @@ -176,7 +189,10 @@ def _extract_data(self, data: list[dict[str, Any]], options: dict[str, Any]) -> if name == "links": # Add a prefix to the referenced link if it is an ID of a need object in # the data retrieved from the Open Needs Server or don't add prefix - value = [(prefix + link if link in ids_of_needs_data else link) for link in value] + value = [ + (prefix + link if link in ids_of_needs_data else link) + for link in value + ] value = ";".join(value) # Ensures mapping option with value == None is not implemented. E.g. the links option # can't be == None since there will be nothing to link to and that will raise a warning @@ -184,7 +200,9 @@ def _extract_data(self, data: list[dict[str, Any]], options: dict[str, Any]) -> need_values[name] = value for regex, new_str in self.mapping_replaces.items(): - need_values[name] = re.sub(regex, new_str, need_values.get(name, "")) + need_values[name] = re.sub( + regex, new_str, need_values.get(name, "") + ) if name == "id": need_values[name] = str(prefix) + str(need_values.get(name, "")) diff --git a/sphinx_needs/utils.py b/sphinx_needs/utils.py index eb0fcccb7..4476c9bb9 100644 --- a/sphinx_needs/utils.py +++ b/sphinx_needs/utils.py @@ -173,8 +173,12 @@ def row_col_maker( link_string_list = {} for link_name, link_conf in needs_config.string_links.items(): link_string_list[link_name] = { - "url_template": Environment(autoescape=True).from_string(link_conf["link_url"]), - "name_template": Environment(autoescape=True).from_string(link_conf["link_name"]), + "url_template": Environment(autoescape=True).from_string( + link_conf["link_url"] + ), + "name_template": Environment(autoescape=True).from_string( + link_conf["link_name"] + ), "regex_compiled": re.compile(link_conf["regex"]), "options": link_conf["options"], "name": link_name, @@ -203,22 +207,34 @@ def row_col_maker( if make_ref: if need_info["is_external"]: - assert need_info["external_url"] is not None, "external_url must be set for external needs" - ref_col["refuri"] = check_and_calc_base_url_rel_path(need_info["external_url"], fromdocname) + assert ( + need_info["external_url"] is not None + ), "external_url must be set for external needs" + ref_col["refuri"] = check_and_calc_base_url_rel_path( + need_info["external_url"], fromdocname + ) ref_col["classes"].append(need_info["external_css"]) row_col["classes"].append(need_info["external_css"]) else: - ref_col["refuri"] = builder.get_relative_uri(fromdocname, need_info["docname"]) + ref_col["refuri"] = builder.get_relative_uri( + fromdocname, need_info["docname"] + ) ref_col["refuri"] += "#" + datum elif ref_lookup: temp_need = all_needs[link_id] if temp_need["is_external"]: - assert temp_need["external_url"] is not None, "external_url must be set for external needs" - ref_col["refuri"] = check_and_calc_base_url_rel_path(temp_need["external_url"], fromdocname) + assert ( + temp_need["external_url"] is not None + ), "external_url must be set for external needs" + ref_col["refuri"] = check_and_calc_base_url_rel_path( + temp_need["external_url"], fromdocname + ) ref_col["classes"].append(temp_need["external_css"]) row_col["classes"].append(temp_need["external_css"]) else: - ref_col["refuri"] = builder.get_relative_uri(fromdocname, temp_need["docname"]) + ref_col["refuri"] = builder.get_relative_uri( + fromdocname, temp_need["docname"] + ) ref_col["refuri"] += "#" + temp_need["id"] if link_part: ref_col["refuri"] += "." + link_part @@ -230,7 +246,11 @@ def row_col_maker( para_col += ref_col elif matching_link_confs: para_col += match_string_link( - datum_text, datum, need_key, matching_link_confs, render_context=needs_config.render_context + datum_text, + datum, + need_key, + matching_link_confs, + render_context=needs_config.render_context, ) else: para_col += text_col @@ -258,7 +278,9 @@ def rstjinja(app: Sphinx, docname: str, source: list[str]) -> None: source[0] = rendered -def import_prefix_link_edit(needs: dict[str, Any], id_prefix: str, needs_extra_links: list[dict[str, Any]]) -> None: +def import_prefix_link_edit( + needs: dict[str, Any], id_prefix: str, needs_extra_links: list[dict[str, Any]] +) -> None: """ Changes existing links to support given prefix. Only link-ids get touched, which are part of ``needs`` (so are linking them). @@ -285,7 +307,9 @@ def import_prefix_link_edit(needs: dict[str, Any], id_prefix: str, needs_extra_l need[extra_link["option"]][n] = f"{id_prefix}{id}" # Manipulate descriptions # ToDo: Use regex for better matches. - need["description"] = need["description"].replace(id, "".join([id_prefix, id])) + need["description"] = need["description"].replace( + id, "".join([id_prefix, id]) + ) FuncT = TypeVar("FuncT") @@ -332,7 +356,11 @@ def check_and_calc_base_url_rel_path(external_url: str, fromdocname: str) -> str # get path sep considering plattform dependency, '\' for Windows, '/' fro Unix curr_path_sep = os.path.sep # check / or \ to determine the relative path to conf.py directory - if not parsed_url.scheme and not os.path.isabs(external_url) and curr_path_sep in fromdocname: + if ( + not parsed_url.scheme + and not os.path.isabs(external_url) + and curr_path_sep in fromdocname + ): sub_level = len(fromdocname.split(curr_path_sep)) - 1 ref_uri = os.path.join(sub_level * (".." + curr_path_sep), external_url) @@ -350,7 +378,8 @@ def check_and_get_external_filter_func(filter_func_ref: str | None) -> tuple[Any filter_module, filter_function = filter_func_ref.rsplit(".") except ValueError: logger.warning( - f'Filter function not valid "{filter_func_ref}". Example: my_module:my_func [needs]', type="needs" + f'Filter function not valid "{filter_func_ref}". Example: my_module:my_func [needs]', + type="needs", ) return filter_func, filter_args @@ -364,7 +393,10 @@ def check_and_get_external_filter_func(filter_func_ref: str | None) -> tuple[Any final_module = importlib.import_module(filter_module) filter_func = getattr(final_module, filter_function) except Exception: - logger.warning(f"Could not import filter function: {filter_func_ref} [needs]", type="needs") + logger.warning( + f"Could not import filter function: {filter_func_ref} [needs]", + type="needs", + ) return filter_func, filter_args return filter_func, filter_args @@ -385,7 +417,10 @@ def jinja_parse(context: dict[str, Any], jinja_string: str) -> str: try: content_template = Template(jinja_string, autoescape=True) except Exception as e: - raise ReferenceError(f'There was an error in the jinja statement: "{jinja_string}". ' f"Error Msg: {e}") + raise ReferenceError( + f'There was an error in the jinja statement: "{jinja_string}". ' + f"Error Msg: {e}" + ) content = content_template.render(**context) return content @@ -407,7 +442,9 @@ def import_matplotlib() -> matplotlib | None: return matplotlib -def save_matplotlib_figure(app: Sphinx, figure: FigureBase, basename: str, fromdocname: str) -> nodes.image: +def save_matplotlib_figure( + app: Sphinx, figure: FigureBase, basename: str, fromdocname: str +) -> nodes.image: builder = app.builder env = app.env @@ -464,20 +501,34 @@ def dict_get(root: dict[str, Any], items: Any, default: Any = None) -> Any: def match_string_link( - text_item: str, data: str, need_key: str, matching_link_confs: list[dict[str, Any]], render_context: dict[str, Any] + text_item: str, + data: str, + need_key: str, + matching_link_confs: list[dict[str, Any]], + render_context: dict[str, Any], ) -> Any: try: link_name = None link_url = None - link_conf = matching_link_confs[0] # We only handle the first matching string_link + link_conf = matching_link_confs[ + 0 + ] # We only handle the first matching string_link match = link_conf["regex_compiled"].search(data) if match: render_content = match.groupdict() - link_url = link_conf["url_template"].render(**render_content, **render_context) - link_name = link_conf["name_template"].render(**render_content, **render_context) + link_url = link_conf["url_template"].render( + **render_content, **render_context + ) + link_name = link_conf["name_template"].render( + **render_content, **render_context + ) # if no string_link match was made, we handle it as normal string value - ref_item = nodes.reference(link_name, link_name, refuri=link_url) if link_name else nodes.Text(text_item) + ref_item = ( + nodes.reference(link_name, link_name, refuri=link_url) + if link_name + else nodes.Text(text_item) + ) except Exception as e: logger.warning( @@ -490,7 +541,9 @@ def match_string_link( def match_variants( - option_value: str | list[str], keywords: dict[str, Any], needs_variants: dict[str, str] + option_value: str | list[str], + keywords: dict[str, Any], + needs_variants: dict[str, str], ) -> None | str | list[str]: """ Function to handle variant option management. @@ -503,7 +556,9 @@ def match_variants( """ def variant_handling( - variant_definitions: list[str], variant_data: dict[str, Any], variant_pattern: Pattern # type: ignore[type-arg] + variant_definitions: list[str], + variant_data: dict[str, Any], + variant_pattern: Pattern, # type: ignore[type-arg] ) -> str | None: filter_context = variant_data # filter_result = [] @@ -515,9 +570,15 @@ def variant_handling( if check_definition: variants_in_option = True # Separate variant definition from value to use for the option - filter_string, output, _ = re.split(r"(:[\w':.\-\" ]+)$", variant_definition) + filter_string, output, _ = re.split( + r"(:[\w':.\-\" ]+)$", variant_definition + ) filter_string = re.sub(r"^\[|[:\]]$", "", filter_string) - filter_string = needs_variants[filter_string] if filter_string in needs_variants else filter_string + filter_string = ( + needs_variants[filter_string] + if filter_string in needs_variants + else filter_string + ) try: # https://docs.python.org/3/library/functions.html?highlight=compile#compile filter_compiled = compile(filter_string, "", "eval") @@ -533,7 +594,8 @@ def variant_handling( return output.lstrip(":") except Exception as e: logger.warning( - f'There was an error in the filter statement: "{filter_string}". ' f"Error Msg: {e} [needs]", + f'There was an error in the filter statement: "{filter_string}". ' + f"Error Msg: {e} [needs]", type="needs", ) else: @@ -557,11 +619,17 @@ def variant_handling( if isinstance(option_value, str): multiple_variants: list[str] = variant_splitting.split(rf"""{option_value}""") multiple_variants = [ - re.sub(r"^([;, ]+)|([;, ]+$)", "", i) for i in multiple_variants if i not in (None, ";", "", " ") + re.sub(r"^([;, ]+)|([;, ]+$)", "", i) + for i in multiple_variants + if i not in (None, ";", "", " ") ] - if len(multiple_variants) == 1 and not variant_rule_matching.search(multiple_variants[0]): + if len(multiple_variants) == 1 and not variant_rule_matching.search( + multiple_variants[0] + ): return option_value - new_option_value = variant_handling(multiple_variants, keywords, variant_rule_matching) + new_option_value = variant_handling( + multiple_variants, keywords, variant_rule_matching + ) if new_option_value is None: return option_value return new_option_value @@ -570,10 +638,14 @@ def variant_handling( # In case an option value is a list (:tags: open; close), and does not contain any variant definition, # then return the unmodified value # options = all([bool(not variant_rule_matching.search(i)) for i in multiple_variants]) - options = all(bool(not variant_rule_matching.search(i)) for i in multiple_variants) + options = all( + bool(not variant_rule_matching.search(i)) for i in multiple_variants + ) if options: return option_value - new_option_value = variant_handling(multiple_variants, keywords, variant_rule_matching) + new_option_value = variant_handling( + multiple_variants, keywords, variant_rule_matching + ) return new_option_value else: return option_value @@ -596,7 +668,9 @@ def clean_log(data: str) -> str: return clean_credentials -def node_match(node_types: type[nodes.Element] | list[type[nodes.Element]]) -> Callable[[nodes.Node], bool]: +def node_match( + node_types: type[nodes.Element] | list[type[nodes.Element]] +) -> Callable[[nodes.Node], bool]: """ Returns a condition function for doctuils.nodes.findall() @@ -618,7 +692,9 @@ def node_match(node_types: type[nodes.Element] | list[type[nodes.Element]]) -> C """ node_types_list = node_types if isinstance(node_types, list) else [node_types] - def condition(node: nodes.Node, node_types: list[type[nodes.Element]] = node_types_list) -> bool: + def condition( + node: nodes.Node, node_types: list[type[nodes.Element]] = node_types_list + ) -> bool: return any(isinstance(node, x) for x in node_types) return condition diff --git a/sphinx_needs/warnings.py b/sphinx_needs/warnings.py index c110e1496..1f9a47c2c 100644 --- a/sphinx_needs/warnings.py +++ b/sphinx_needs/warnings.py @@ -61,7 +61,9 @@ def process_warnings(app: Sphinx, exception: Exception | None) -> None: for warning_name, warning_filter in NEEDS_CONFIG.warnings.items(): if isinstance(warning_filter, str): # filter string used - result = filter_needs(checked_needs.values(), needs_config, warning_filter) + result = filter_needs( + checked_needs.values(), needs_config, warning_filter + ) elif callable(warning_filter): # custom defined filter code used from conf.py result = [] @@ -69,7 +71,10 @@ def process_warnings(app: Sphinx, exception: Exception | None) -> None: if warning_filter(need, logger): result.append(need) else: - logger.warning(f"Unknown needs warnings filter {warning_filter}! [needs]", type="needs") + logger.warning( + f"Unknown needs warnings filter {warning_filter}! [needs]", + type="needs", + ) if len(result) == 0: logger.info(f"{warning_name}: passed") @@ -94,17 +99,26 @@ def process_warnings(app: Sphinx, exception: Exception | None) -> None: if warnings_always_warn: logger.warning( "{}: failed\n\t\tfailed needs: {} ({})\n\t\tused filter: {} [needs]".format( - warning_name, len(need_ids), ", ".join(need_ids), warning_text + warning_name, + len(need_ids), + ", ".join(need_ids), + warning_text, ), type="needs", ) else: logger.info( "{}: failed\n\t\tfailed needs: {} ({})\n\t\tused filter: {}".format( - warning_name, len(need_ids), ", ".join(need_ids), warning_text + warning_name, + len(need_ids), + ", ".join(need_ids), + warning_text, ) ) warning_raised = True if warning_raised: - logger.warning("warnings were raised. See console / log output for details. [needs]", type="needs") + logger.warning( + "warnings were raised. See console / log output for details. [needs]", + type="needs", + ) diff --git a/tests/benchmarks/test_basic.py b/tests/benchmarks/test_basic.py index 02c329101..a45133136 100644 --- a/tests/benchmarks/test_basic.py +++ b/tests/benchmarks/test_basic.py @@ -8,7 +8,9 @@ @responses.activate -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_basic"}], indirect=True) +@pytest.mark.parametrize( + "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_basic"}], indirect=True +) def test_basic_time(test_app, benchmark): responses.add_callback( responses.GET, @@ -16,7 +18,9 @@ def test_basic_time(test_app, benchmark): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) app = test_app benchmark.pedantic(app.builder.build_all, rounds=1, iterations=1) diff --git a/tests/benchmarks/test_official.py b/tests/benchmarks/test_official.py index b2f3ba6a8..663a3ea86 100644 --- a/tests/benchmarks/test_official.py +++ b/tests/benchmarks/test_official.py @@ -9,7 +9,9 @@ @responses.activate -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "../docs"}], indirect=True) +@pytest.mark.parametrize( + "test_app", [{"buildername": "html", "srcdir": "../docs"}], indirect=True +) def test_official_time(test_app, benchmark): responses.add_callback( responses.GET, @@ -17,7 +19,9 @@ def test_official_time(test_app, benchmark): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) app = test_app benchmark.pedantic(app.builder.build_all, rounds=1, iterations=1) @@ -29,7 +33,11 @@ def test_official_time(test_app, benchmark): @responses.activate -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "../docs", "parallel": 1}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "../docs", "parallel": 1}], + indirect=True, +) def test_official_memory(test_app): responses.add_callback( responses.GET, @@ -37,7 +45,9 @@ def test_official_memory(test_app): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) app = test_app diff --git a/tests/conftest.py b/tests/conftest.py index c631b27fc..e39cd8524 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -83,7 +83,16 @@ class Starter(ProcessStarter): pattern = "Serving HTTP on [0-9.]+ port 62343|Address already in use" timeout = 20 terminate_on_interrupt = True - args = ["python3", "-m", "http.server", "--directory", sphinx_test_tempdir, "--bind", addr, port] + args = [ + "python3", + "-m", + "http.server", + "--directory", + sphinx_test_tempdir, + "--bind", + addr, + port, + ] env = {"PYTHONUNBUFFERED": "1"} def check_server_connection(log_path: str): @@ -98,13 +107,18 @@ def check_server_connection(log_path: str): sock.close() if result == 0: with open(str(log_path), "wb", 0) as stdout: - stdout.write(bytes("Serving HTTP on 127.0.0.1 port 62343 (http://127.0.0.1:62343/) ...\n", "utf8")) + stdout.write( + bytes( + "Serving HTTP on 127.0.0.1 port 62343 (http://127.0.0.1:62343/) ...\n", + "utf8", + ) + ) return True return False if not check_server_connection(log_path=xprocess.getinfo("http_server").logpath): # Start the process and ensure it is running - _, logfile = xprocess.ensure("http_server", Starter, persist_logs=False) # noqa:F841 + _, logfile = xprocess.ensure("http_server", Starter, persist_logs=False) http_server_process = xprocess.getinfo("http_server") server_url = f"http://{addr}:{port}" @@ -129,7 +143,9 @@ def test_js(self) -> Dict[str, Any]: """ cypress_testpath = get_abspath(self.spec_pattern) - if not cypress_testpath or not (os.path.isabs(cypress_testpath) and os.path.exists(cypress_testpath)): + if not cypress_testpath or not ( + os.path.isabs(cypress_testpath) and os.path.exists(cypress_testpath) + ): return { "returncode": 1, "stdout": None, @@ -179,7 +195,12 @@ def test_js(self) -> Dict[str, Any]: def pytest_addoption(parser): - parser.addoption("--sn-build-dir", action="store", default=None, help="Base directory for sphinx-needs builds") + parser.addoption( + "--sn-build-dir", + action="store", + default=None, + help="Base directory for sphinx-needs builds", + ) @pytest.fixture(scope="session") @@ -195,7 +216,9 @@ def sphinx_test_tempdir(request) -> path: # We create a temp-folder on our own, as the util-functions from sphinx and pytest make troubles. # It seems like they reuse certain-temp names - temp_base = os.path.abspath(request.config.getoption("--sn-build-dir") or tempfile.gettempdir()) + temp_base = os.path.abspath( + request.config.getoption("--sn-build-dir") or tempfile.gettempdir() + ) sphinx_test_tempdir = path(temp_base).joinpath("sn_test_build_data") utils_dir = sphinx_test_tempdir.joinpath("utils") @@ -235,7 +258,9 @@ def test_app(make_app, sphinx_test_tempdir, request): if not builder_params.get("no_plantuml", False): # Since we don't want copy the plantuml.jar file for each test function, # we need to override the plantuml conf variable and set it to what we have already - plantuml = "java -Djava.awt.headless=true -jar %s" % os.path.join(sphinx_test_tempdir, "utils", "plantuml.jar") + plantuml = "java -Djava.awt.headless=true -jar %s" % os.path.join( + sphinx_test_tempdir, "utils", "plantuml.jar" + ) sphinx_conf_overrides.update(plantuml=plantuml) # copy test srcdir to test temporary directory sphinx_test_tempdir diff --git a/tests/data/service_github.py b/tests/data/service_github.py index fb24ab4d8..9151feb32 100644 --- a/tests/data/service_github.py +++ b/tests/data/service_github.py @@ -108,7 +108,8 @@ GITHUB_SPECIFIC_ISSUE_ANSWER = { "url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/issues/141", "repository_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs", - "labels_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/issues/" "141/labels{/name}", + "labels_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/issues/" + "141/labels{/name}", "comments_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/issues/141/comments", "events_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/issues/141/events", "html_url": "https://github.com/useblocks/sphinxcontrib-needs/issues/141", @@ -140,7 +141,8 @@ { "id": 491973814, "node_id": "MDU6TGFiZWw0OTE5NzM4MTQ=", - "url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs" "/labels/bug", + "url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs" + "/labels/bug", "name": "bug", "color": "ee0701", "default": True, @@ -318,7 +320,8 @@ "/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/teams", "hooks_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/hooks", - "issue_events_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/issues/events{" "/number}", + "issue_events_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/issues/events{" + "/number}", "events_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/events", "assignees_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/assignees{/user}", "branches_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/branches{/branch}", @@ -334,17 +337,22 @@ "subscribers_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/subscribers", "subscription_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/subscription", "commits_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/git" "/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/git" + "/commits{/sha}", "comments_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/issues" "/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/issues" + "/comments{/number}", "contents_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/contents/{+path}", - "compare_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/compare/{base}...{" "head}", + "compare_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/compare/{base}...{" + "head}", "merges_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/merges", - "archive_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/{archive_format}{" "/ref}", + "archive_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/{archive_format}{" + "/ref}", "downloads_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/downloads", "issues_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/issues{/number}", "pulls_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/pulls{/number}", - "milestones_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/milestones{" "/number}", + "milestones_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/milestones{" + "/number}", "notifications_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs" "/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/useblocks/sphinxcontrib-needs/labels{/name}", diff --git a/tests/doc_test/api_doc/conf.py b/tests/doc_test/api_doc/conf.py index 7832f346d..df50838b8 100644 --- a/tests/doc_test/api_doc/conf.py +++ b/tests/doc_test/api_doc/conf.py @@ -1,8 +1,32 @@ extensions = ["sphinx_needs", "dummy_extension.dummy"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/api_doc_awesome/conf.py b/tests/doc_test/api_doc_awesome/conf.py index 7832f346d..df50838b8 100644 --- a/tests/doc_test/api_doc_awesome/conf.py +++ b/tests/doc_test/api_doc_awesome/conf.py @@ -1,8 +1,32 @@ extensions = ["sphinx_needs", "dummy_extension.dummy"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/arch_doc/conf.py b/tests/doc_test/arch_doc/conf.py index 1571c763f..70ce823f5 100644 --- a/tests/doc_test/arch_doc/conf.py +++ b/tests/doc_test/arch_doc/conf.py @@ -3,8 +3,32 @@ plantuml_output_format = "svg" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/broken_doc/conf.py b/tests/doc_test/broken_doc/conf.py index 21eab6d52..1b74e151a 100644 --- a/tests/doc_test/broken_doc/conf.py +++ b/tests/doc_test/broken_doc/conf.py @@ -1,8 +1,32 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/broken_links/conf.py b/tests/doc_test/broken_links/conf.py index 21eab6d52..1b74e151a 100644 --- a/tests/doc_test/broken_links/conf.py +++ b/tests/doc_test/broken_links/conf.py @@ -1,8 +1,32 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/broken_statuses/conf.py b/tests/doc_test/broken_statuses/conf.py index 3706ca5ff..6e013eae5 100644 --- a/tests/doc_test/broken_statuses/conf.py +++ b/tests/doc_test/broken_statuses/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_statuses = [ diff --git a/tests/doc_test/broken_syntax_doc/conf.py b/tests/doc_test/broken_syntax_doc/conf.py index 21eab6d52..1b74e151a 100644 --- a/tests/doc_test/broken_syntax_doc/conf.py +++ b/tests/doc_test/broken_syntax_doc/conf.py @@ -1,8 +1,32 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/broken_tags/conf.py b/tests/doc_test/broken_tags/conf.py index 7c04d916c..6559d7fe0 100644 --- a/tests/doc_test/broken_tags/conf.py +++ b/tests/doc_test/broken_tags/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_tags = [ diff --git a/tests/doc_test/broken_tags_2/conf.py b/tests/doc_test/broken_tags_2/conf.py index 7c04d916c..6559d7fe0 100644 --- a/tests/doc_test/broken_tags_2/conf.py +++ b/tests/doc_test/broken_tags_2/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_tags = [ diff --git a/tests/doc_test/doc_basic/conf.py b/tests/doc_test/doc_basic/conf.py index 0a5cb1761..2db347716 100644 --- a/tests/doc_test/doc_basic/conf.py +++ b/tests/doc_test/doc_basic/conf.py @@ -6,8 +6,32 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_basic_latex/conf.py b/tests/doc_test/doc_basic_latex/conf.py index 32f8e8de5..1f9bcc6ed 100644 --- a/tests/doc_test/doc_basic_latex/conf.py +++ b/tests/doc_test/doc_basic_latex/conf.py @@ -8,8 +8,32 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_build_latex/conf.py b/tests/doc_test/doc_build_latex/conf.py index 6a81ad4bb..df70aa270 100644 --- a/tests/doc_test/doc_build_latex/conf.py +++ b/tests/doc_test/doc_build_latex/conf.py @@ -13,8 +13,32 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_df_calc_sum/conf.py b/tests/doc_test/doc_df_calc_sum/conf.py index 2e1bb2cf3..ee4795ac0 100644 --- a/tests/doc_test/doc_df_calc_sum/conf.py +++ b/tests/doc_test/doc_df_calc_sum/conf.py @@ -3,10 +3,38 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] -needs_extra_options = {"test_func": directives.unchanged, "hours": directives.unchanged, "amount": directives.unchanged} +needs_extra_options = { + "test_func": directives.unchanged, + "hours": directives.unchanged, + "amount": directives.unchanged, +} diff --git a/tests/doc_test/doc_df_check_linked_values/conf.py b/tests/doc_test/doc_df_check_linked_values/conf.py index 707f3afad..2a93cda81 100644 --- a/tests/doc_test/doc_df_check_linked_values/conf.py +++ b/tests/doc_test/doc_df_check_linked_values/conf.py @@ -3,10 +3,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_options = {"test_func": directives.unchanged, "hours": directives.unchanged} diff --git a/tests/doc_test/doc_df_user_functions/conf.py b/tests/doc_test/doc_df_user_functions/conf.py index 07958c0c0..14945940d 100644 --- a/tests/doc_test/doc_df_user_functions/conf.py +++ b/tests/doc_test/doc_df_user_functions/conf.py @@ -3,10 +3,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_options = {"test_func": directives.unchanged, "hours": directives.unchanged} diff --git a/tests/doc_test/doc_dynamic_functions/conf.py b/tests/doc_test/doc_dynamic_functions/conf.py index 5097fc12d..e474af668 100644 --- a/tests/doc_test/doc_dynamic_functions/conf.py +++ b/tests/doc_test/doc_dynamic_functions/conf.py @@ -3,10 +3,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_options = {"test_func": directives.unchanged} diff --git a/tests/doc_test/doc_export_id/conf.py b/tests/doc_test/doc_export_id/conf.py index 34095785f..d2a706459 100644 --- a/tests/doc_test/doc_export_id/conf.py +++ b/tests/doc_test/doc_export_id/conf.py @@ -6,10 +6,34 @@ plantuml_output_format = "svg" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_links = [ diff --git a/tests/doc_test/doc_extra_links/conf.py b/tests/doc_test/doc_extra_links/conf.py index ad8a7f24e..863b56681 100644 --- a/tests/doc_test/doc_extra_links/conf.py +++ b/tests/doc_test/doc_extra_links/conf.py @@ -6,10 +6,34 @@ plantuml_output_format = "svg" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_links = [ diff --git a/tests/doc_test/doc_github_issue_21/conf.py b/tests/doc_test/doc_github_issue_21/conf.py index 21eab6d52..1b74e151a 100644 --- a/tests/doc_test/doc_github_issue_21/conf.py +++ b/tests/doc_test/doc_github_issue_21/conf.py @@ -1,8 +1,32 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_github_issue_44/conf.py b/tests/doc_test/doc_github_issue_44/conf.py index df3fe57f8..7556c0c4e 100644 --- a/tests/doc_test/doc_github_issue_44/conf.py +++ b/tests/doc_test/doc_github_issue_44/conf.py @@ -3,8 +3,32 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_global_options/conf.py b/tests/doc_test/doc_global_options/conf.py index 46408adc5..f22187cad 100644 --- a/tests/doc_test/doc_global_options/conf.py +++ b/tests/doc_test/doc_global_options/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_global_options = { diff --git a/tests/doc_test/doc_layout/conf.py b/tests/doc_test/doc_layout/conf.py index 6969f1c23..899d6306c 100644 --- a/tests/doc_test/doc_layout/conf.py +++ b/tests/doc_test/doc_layout/conf.py @@ -3,10 +3,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_options = { @@ -19,7 +43,10 @@ "grid": "simple_side_right_partial", "layout": { "head": ['**<>** for *<>*'], - "meta": ['**status**: <>', '**author**: <>'], + "meta": [ + '**status**: <>', + '**author**: <>', + ], "side": ['<>'], }, }, @@ -27,14 +54,20 @@ "grid": "simple", "layout": { "head": ['**<>**'], - "meta": ['**status**: <>', r'<>'], + "meta": [ + '**status**: <>', + r'<>', + ], }, }, "footer_grid": { "grid": "simple_footer", "layout": { "head": ['**<>** for *<>*'], - "meta": ['**status**: <>', '**author**: <>'], + "meta": [ + '**status**: <>', + '**author**: <>', + ], "footer": ['**custom footer for <>**'], }, }, diff --git a/tests/doc_test/doc_list2need/conf.py b/tests/doc_test/doc_list2need/conf.py index 009477a1b..43d93e5f4 100644 --- a/tests/doc_test/doc_list2need/conf.py +++ b/tests/doc_test/doc_list2need/conf.py @@ -8,10 +8,34 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_links = [ diff --git a/tests/doc_test/doc_measure_time/conf.py b/tests/doc_test/doc_measure_time/conf.py index 74f164462..a4b1d4e5f 100644 --- a/tests/doc_test/doc_measure_time/conf.py +++ b/tests/doc_test/doc_measure_time/conf.py @@ -17,10 +17,34 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_need_count/conf.py b/tests/doc_test/doc_need_count/conf.py index 21eab6d52..1b74e151a 100644 --- a/tests/doc_test/doc_need_count/conf.py +++ b/tests/doc_test/doc_need_count/conf.py @@ -1,8 +1,32 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_need_delete/conf.py b/tests/doc_test/doc_need_delete/conf.py index 104609b54..3badaf917 100644 --- a/tests/doc_test/doc_need_delete/conf.py +++ b/tests/doc_test/doc_need_delete/conf.py @@ -6,8 +6,32 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "R_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "R_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_need_id_from_title/conf.py b/tests/doc_test/doc_need_id_from_title/conf.py index e3a53e73b..d7e949123 100644 --- a/tests/doc_test/doc_need_id_from_title/conf.py +++ b/tests/doc_test/doc_need_id_from_title/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_id_length = 20 diff --git a/tests/doc_test/doc_need_jinja_content/conf.py b/tests/doc_test/doc_need_jinja_content/conf.py index 3f7d3cdd7..6081c7b09 100644 --- a/tests/doc_test/doc_need_jinja_content/conf.py +++ b/tests/doc_test/doc_need_jinja_content/conf.py @@ -6,10 +6,34 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "R_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "R_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_need_parts/conf.py b/tests/doc_test/doc_need_parts/conf.py index 21eab6d52..1b74e151a 100644 --- a/tests/doc_test/doc_need_parts/conf.py +++ b/tests/doc_test/doc_need_parts/conf.py @@ -1,8 +1,32 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needarch/conf.py b/tests/doc_test/doc_needarch/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needarch/conf.py +++ b/tests/doc_test/doc_needarch/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needarch_jinja_func_import/conf.py b/tests/doc_test/doc_needarch_jinja_func_import/conf.py index dfccf97c2..f20c68b8c 100644 --- a/tests/doc_test/doc_needarch_jinja_func_import/conf.py +++ b/tests/doc_test/doc_needarch_jinja_func_import/conf.py @@ -20,7 +20,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -29,10 +36,34 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_links = [ @@ -41,5 +72,10 @@ "incoming": "is used by", "outgoing": "uses", }, - {"option": "tests", "incoming": "is tested by", "outgoing": "tests", "style": "#00AA00"}, + { + "option": "tests", + "incoming": "is tested by", + "outgoing": "tests", + "style": "#00AA00", + }, ] diff --git a/tests/doc_test/doc_needarch_jinja_func_need/conf.py b/tests/doc_test/doc_needarch_jinja_func_need/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needarch_jinja_func_need/conf.py +++ b/tests/doc_test/doc_needarch_jinja_func_need/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needarch_negative_tests/conf.py b/tests/doc_test/doc_needarch_negative_tests/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needarch_negative_tests/conf.py +++ b/tests/doc_test/doc_needarch_negative_tests/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needbar/conf.py b/tests/doc_test/doc_needbar/conf.py index 0d9b66fe3..c0dc66839 100644 --- a/tests/doc_test/doc_needbar/conf.py +++ b/tests/doc_test/doc_needbar/conf.py @@ -3,6 +3,18 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "RQ_", "color": "#FEDCD2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "RQ_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needextend/conf.py b/tests/doc_test/doc_needextend/conf.py index 08df9747f..4c07658ee 100644 --- a/tests/doc_test/doc_needextend/conf.py +++ b/tests/doc_test/doc_needextend/conf.py @@ -3,8 +3,32 @@ needs_build_json = True needs_id_regex = "^[A-Za-z0-9_]*" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needextend_strict/conf.py b/tests/doc_test/doc_needextend_strict/conf.py index 6b4b9fa9d..99f842750 100644 --- a/tests/doc_test/doc_needextend_strict/conf.py +++ b/tests/doc_test/doc_needextend_strict/conf.py @@ -2,8 +2,32 @@ needs_id_regex = "^[A-Za-z0-9_]*" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needextract/conf.py b/tests/doc_test/doc_needextract/conf.py index 47badfa7d..87cb4ac0e 100644 --- a/tests/doc_test/doc_needextract/conf.py +++ b/tests/doc_test/doc_needextract/conf.py @@ -8,8 +8,32 @@ needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needflow/conf.py b/tests/doc_test/doc_needflow/conf.py index aa6219420..aab24df0d 100644 --- a/tests/doc_test/doc_needflow/conf.py +++ b/tests/doc_test/doc_needflow/conf.py @@ -8,8 +8,32 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needflow_incl_child_needs/conf.py b/tests/doc_test/doc_needflow_incl_child_needs/conf.py index 24b1cbd1b..96753e0bd 100644 --- a/tests/doc_test/doc_needflow_incl_child_needs/conf.py +++ b/tests/doc_test/doc_needflow_incl_child_needs/conf.py @@ -8,10 +8,34 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needimport_download_needs_json/conf.py b/tests/doc_test/doc_needimport_download_needs_json/conf.py index 885bd47d6..814c929f3 100644 --- a/tests/doc_test/doc_needimport_download_needs_json/conf.py +++ b/tests/doc_test/doc_needimport_download_needs_json/conf.py @@ -3,8 +3,32 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needimport_download_needs_json_negative/conf.py b/tests/doc_test/doc_needimport_download_needs_json_negative/conf.py index 885bd47d6..814c929f3 100644 --- a/tests/doc_test/doc_needimport_download_needs_json_negative/conf.py +++ b/tests/doc_test/doc_needimport_download_needs_json_negative/conf.py @@ -3,8 +3,32 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needlist/conf.py b/tests/doc_test/doc_needlist/conf.py index 885bd47d6..814c929f3 100644 --- a/tests/doc_test/doc_needlist/conf.py +++ b/tests/doc_test/doc_needlist/conf.py @@ -3,8 +3,32 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needpie/conf.py b/tests/doc_test/doc_needpie/conf.py index 86ef3ff45..2c635d301 100644 --- a/tests/doc_test/doc_needpie/conf.py +++ b/tests/doc_test/doc_needpie/conf.py @@ -8,10 +8,34 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_options = ["author"] diff --git a/tests/doc_test/doc_needs_builder/conf.py b/tests/doc_test/doc_needs_builder/conf.py index ce1cbf2cf..0e12a0867 100644 --- a/tests/doc_test/doc_needs_builder/conf.py +++ b/tests/doc_test/doc_needs_builder/conf.py @@ -5,10 +5,34 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_file = "custom_needs_test.json" diff --git a/tests/doc_test/doc_needs_builder_negative_tests/conf.py b/tests/doc_test/doc_needs_builder_negative_tests/conf.py index 885bd47d6..814c929f3 100644 --- a/tests/doc_test/doc_needs_builder_negative_tests/conf.py +++ b/tests/doc_test/doc_needs_builder_negative_tests/conf.py @@ -3,8 +3,32 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needs_builder_parallel/conf.py b/tests/doc_test/doc_needs_builder_parallel/conf.py index 87abb2f42..dabfbcfcf 100644 --- a/tests/doc_test/doc_needs_builder_parallel/conf.py +++ b/tests/doc_test/doc_needs_builder_parallel/conf.py @@ -7,10 +7,34 @@ needs_build_json = True needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_file = "custom_needs_test.json" diff --git a/tests/doc_test/doc_needs_external_needs/conf.py b/tests/doc_test/doc_needs_external_needs/conf.py index 95e5cee80..2d787751d 100644 --- a/tests/doc_test/doc_needs_external_needs/conf.py +++ b/tests/doc_test/doc_needs_external_needs/conf.py @@ -6,13 +6,45 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_external_needs = [ - {"base_url": "http://my_company.com/docs/v1/", "json_path": "needs_test_small.json", "id_prefix": "ext_"}, - {"base_url": "../../_build/html", "json_path": "needs_test_small.json", "id_prefix": "ext_rel_path_"}, + { + "base_url": "http://my_company.com/docs/v1/", + "json_path": "needs_test_small.json", + "id_prefix": "ext_", + }, + { + "base_url": "../../_build/html", + "json_path": "needs_test_small.json", + "id_prefix": "ext_rel_path_", + }, ] diff --git a/tests/doc_test/doc_needs_external_needs_remote/conf.py b/tests/doc_test/doc_needs_external_needs_remote/conf.py index b63ea602c..460476c0b 100644 --- a/tests/doc_test/doc_needs_external_needs_remote/conf.py +++ b/tests/doc_test/doc_needs_external_needs_remote/conf.py @@ -6,10 +6,34 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_external_needs = [ diff --git a/tests/doc_test/doc_needs_external_needs_with_target_url/conf.py b/tests/doc_test/doc_needs_external_needs_with_target_url/conf.py index d4c198d2d..6a45a59f8 100644 --- a/tests/doc_test/doc_needs_external_needs_with_target_url/conf.py +++ b/tests/doc_test/doc_needs_external_needs_with_target_url/conf.py @@ -6,10 +6,34 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_external_needs = [ @@ -31,5 +55,9 @@ "json_path": "needs_test_small.json", "id_prefix": "ext_need_type_", }, - {"base_url": "http://my_company.com/docs/v1/", "json_path": "needs_test_small.json", "id_prefix": "ext_default_"}, + { + "base_url": "http://my_company.com/docs/v1/", + "json_path": "needs_test_small.json", + "id_prefix": "ext_default_", + }, ] diff --git a/tests/doc_test/doc_needs_filter_data/conf.py b/tests/doc_test/doc_needs_filter_data/conf.py index 23aa68579..8c62e9c97 100644 --- a/tests/doc_test/doc_needs_filter_data/conf.py +++ b/tests/doc_test/doc_needs_filter_data/conf.py @@ -12,10 +12,34 @@ needs_id_regex = "^[A-Za-z0-9_]*" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needs_filter_func_allow_dirty_filter/conf.py b/tests/doc_test/doc_needs_filter_func_allow_dirty_filter/conf.py index 6d7baed7d..3361ea436 100644 --- a/tests/doc_test/doc_needs_filter_func_allow_dirty_filter/conf.py +++ b/tests/doc_test/doc_needs_filter_func_allow_dirty_filter/conf.py @@ -8,8 +8,20 @@ needs_id_regex = "^[A-Za-z0-9_]*" needs_types = [ - {"directive": "feature", "title": "Feature", "prefix": "FE_", "color": "#FEDCD2", "style": "node"}, - {"directive": "usecase", "title": "Use Case", "prefix": "USE_", "color": "#DF744A", "style": "node"}, + { + "directive": "feature", + "title": "Feature", + "prefix": "FE_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "usecase", + "title": "Use Case", + "prefix": "USE_", + "color": "#DF744A", + "style": "node", + }, ] needs_extra_options = ["ti", "tcl"] diff --git a/tests/doc_test/doc_needs_warnings/conf.py b/tests/doc_test/doc_needs_warnings/conf.py index f6b991773..cfc630c88 100644 --- a/tests/doc_test/doc_needs_warnings/conf.py +++ b/tests/doc_test/doc_needs_warnings/conf.py @@ -3,14 +3,42 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_external_needs = [ - {"base_url": "http://my_company.com/docs/v1/", "json_path": "needs_test_small.json", "id_prefix": "ext_"} + { + "base_url": "http://my_company.com/docs/v1/", + "json_path": "needs_test_small.json", + "id_prefix": "ext_", + } ] @@ -38,7 +66,11 @@ def setup(app): add_warning(app, "api_warning_filter", filter_string="status == 'example_2'") add_warning(app, "api_warning_func", custom_warning_func) - add_warning(app, "invalid_status", "status not in ['open', 'closed', 'done', 'example_2', 'example_3']") + add_warning( + app, + "invalid_status", + "status not in ['open', 'closed', 'done', 'example_2', 'example_3']", + ) # Needs option to set True or False to raise sphinx-warning for each not passed warning check diff --git a/tests/doc_test/doc_needs_warnings_return_status_code/conf.py b/tests/doc_test/doc_needs_warnings_return_status_code/conf.py index 490cb7534..47d7db034 100644 --- a/tests/doc_test/doc_needs_warnings_return_status_code/conf.py +++ b/tests/doc_test/doc_needs_warnings_return_status_code/conf.py @@ -3,10 +3,34 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needsfile/conf.py b/tests/doc_test/doc_needsfile/conf.py index e607e1f34..457adbf2a 100644 --- a/tests/doc_test/doc_needsfile/conf.py +++ b/tests/doc_test/doc_needsfile/conf.py @@ -3,8 +3,32 @@ needs_file = "needs_errors.json" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needtable/conf.py b/tests/doc_test/doc_needtable/conf.py index 73fd61077..0aef9a7d0 100644 --- a/tests/doc_test/doc_needtable/conf.py +++ b/tests/doc_test/doc_needtable/conf.py @@ -5,10 +5,34 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_options = [ diff --git a/tests/doc_test/doc_needuml/conf.py b/tests/doc_test/doc_needuml/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needuml/conf.py +++ b/tests/doc_test/doc_needuml/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needuml_diagram_allowmixing/conf.py b/tests/doc_test/doc_needuml_diagram_allowmixing/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needuml_diagram_allowmixing/conf.py +++ b/tests/doc_test/doc_needuml_diagram_allowmixing/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needuml_duplicate_key/conf.py b/tests/doc_test/doc_needuml_duplicate_key/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needuml_duplicate_key/conf.py +++ b/tests/doc_test/doc_needuml_duplicate_key/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needuml_filter/conf.py b/tests/doc_test/doc_needuml_filter/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needuml_filter/conf.py +++ b/tests/doc_test/doc_needuml_filter/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needuml_jinja_func_flow/conf.py b/tests/doc_test/doc_needuml_jinja_func_flow/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needuml_jinja_func_flow/conf.py +++ b/tests/doc_test/doc_needuml_jinja_func_flow/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needuml_jinja_func_import_negative_tests/conf.py b/tests/doc_test/doc_needuml_jinja_func_import_negative_tests/conf.py index dfccf97c2..f20c68b8c 100644 --- a/tests/doc_test/doc_needuml_jinja_func_import_negative_tests/conf.py +++ b/tests/doc_test/doc_needuml_jinja_func_import_negative_tests/conf.py @@ -20,7 +20,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -29,10 +36,34 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_links = [ @@ -41,5 +72,10 @@ "incoming": "is used by", "outgoing": "uses", }, - {"option": "tests", "incoming": "is tested by", "outgoing": "tests", "style": "#00AA00"}, + { + "option": "tests", + "incoming": "is tested by", + "outgoing": "tests", + "style": "#00AA00", + }, ] diff --git a/tests/doc_test/doc_needuml_jinja_func_need_removed/conf.py b/tests/doc_test/doc_needuml_jinja_func_need_removed/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needuml_jinja_func_need_removed/conf.py +++ b/tests/doc_test/doc_needuml_jinja_func_need_removed/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needuml_jinja_func_ref/conf.py b/tests/doc_test/doc_needuml_jinja_func_ref/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needuml_jinja_func_ref/conf.py +++ b/tests/doc_test/doc_needuml_jinja_func_ref/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needuml_key_name_diagram/conf.py b/tests/doc_test/doc_needuml_key_name_diagram/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needuml_key_name_diagram/conf.py +++ b/tests/doc_test/doc_needuml_key_name_diagram/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_needuml_save/conf.py b/tests/doc_test/doc_needuml_save/conf.py index e4c6437fd..ad06ccaad 100644 --- a/tests/doc_test/doc_needuml_save/conf.py +++ b/tests/doc_test/doc_needuml_save/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,10 +38,34 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_build_needumls = "my_needumls" diff --git a/tests/doc_test/doc_needuml_save_with_abs_path/conf.py b/tests/doc_test/doc_needuml_save_with_abs_path/conf.py index 1666acffc..208a58691 100644 --- a/tests/doc_test/doc_needuml_save_with_abs_path/conf.py +++ b/tests/doc_test/doc_needuml_save_with_abs_path/conf.py @@ -22,7 +22,14 @@ "color": "#BFD8D2", "style": "card", }, - {"directive": "sys", "content": "plantuml", "title": "System", "prefix": "S_", "color": "#FF68D2", "style": "node"}, + { + "directive": "sys", + "content": "plantuml", + "title": "System", + "prefix": "S_", + "color": "#FF68D2", + "style": "node", + }, { "directive": "prod", "content": "plantuml", @@ -31,8 +38,32 @@ "color": "#FF68D2", "style": "node", }, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/doc_open_needs_service/conf.py b/tests/doc_test/doc_open_needs_service/conf.py index be86e0012..50d1c74d3 100644 --- a/tests/doc_test/doc_open_needs_service/conf.py +++ b/tests/doc_test/doc_open_needs_service/conf.py @@ -3,10 +3,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "R_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "task", "title": "Task", "prefix": "T_", "color": "#DCB239", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "R_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "task", + "title": "Task", + "prefix": "T_", + "color": "#DCB239", + "style": "node", + }, ] needs_services = { diff --git a/tests/doc_test/doc_report_dead_links_false/conf.py b/tests/doc_test/doc_report_dead_links_false/conf.py index 813f445a4..ae1448dee 100644 --- a/tests/doc_test/doc_report_dead_links_false/conf.py +++ b/tests/doc_test/doc_report_dead_links_false/conf.py @@ -4,10 +4,34 @@ plantuml_output_format = "svg" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] suppress_warnings = ["needs.link_outgoing"] diff --git a/tests/doc_test/doc_report_dead_links_true/conf.py b/tests/doc_test/doc_report_dead_links_true/conf.py index 91467f963..e114d9518 100644 --- a/tests/doc_test/doc_report_dead_links_true/conf.py +++ b/tests/doc_test/doc_report_dead_links_true/conf.py @@ -4,10 +4,34 @@ plantuml_output_format = "svg" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_extra_links = [ diff --git a/tests/doc_test/doc_role_need_max_title_length/conf.py b/tests/doc_test/doc_role_need_max_title_length/conf.py index 46b0b1685..11f882b66 100644 --- a/tests/doc_test/doc_role_need_max_title_length/conf.py +++ b/tests/doc_test/doc_role_need_max_title_length/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_role_need_template = "[{id}] {title} ({status}) {type_name}/{type} - {tags} - {links} - {links_back} - {content}" diff --git a/tests/doc_test/doc_role_need_max_title_length_unlimited/conf.py b/tests/doc_test/doc_role_need_max_title_length_unlimited/conf.py index 23dec017c..0a85db025 100644 --- a/tests/doc_test/doc_role_need_max_title_length_unlimited/conf.py +++ b/tests/doc_test/doc_role_need_max_title_length_unlimited/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_role_need_template = "[{id}] {title} ({status}) {type_name}/{type} - {tags} - {links} - {links_back} - {content}" diff --git a/tests/doc_test/doc_role_need_template/conf.py b/tests/doc_test/doc_role_need_template/conf.py index 4d15bdb0d..fa86a8027 100644 --- a/tests/doc_test/doc_role_need_template/conf.py +++ b/tests/doc_test/doc_role_need_template/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_role_need_template = "[{id}] {title} ({status}) {type_name}/{type} - {tags} - {links} - {links_back} - {content}" diff --git a/tests/doc_test/doc_style_blank/conf.py b/tests/doc_test/doc_style_blank/conf.py index ef8a46842..959f7f07b 100644 --- a/tests/doc_test/doc_style_blank/conf.py +++ b/tests/doc_test/doc_style_blank/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_css = "blank.css" diff --git a/tests/doc_test/doc_style_custom/conf.py b/tests/doc_test/doc_style_custom/conf.py index 80485dc17..ed2820a9b 100644 --- a/tests/doc_test/doc_style_custom/conf.py +++ b/tests/doc_test/doc_style_custom/conf.py @@ -3,10 +3,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_css = os.path.join(os.path.dirname(__file__), "my_custom.css") diff --git a/tests/doc_test/doc_style_modern/conf.py b/tests/doc_test/doc_style_modern/conf.py index 68f00c54c..51fd8c41c 100644 --- a/tests/doc_test/doc_style_modern/conf.py +++ b/tests/doc_test/doc_style_modern/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_css = "modern.css" diff --git a/tests/doc_test/doc_style_unknown/conf.py b/tests/doc_test/doc_style_unknown/conf.py index ec0cfafe9..8ee6fe502 100644 --- a/tests/doc_test/doc_style_unknown/conf.py +++ b/tests/doc_test/doc_style_unknown/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_css = "UNKNOWN.css" diff --git a/tests/doc_test/external_doc/conf.py b/tests/doc_test/external_doc/conf.py index e38367471..c884b37f9 100644 --- a/tests/doc_test/external_doc/conf.py +++ b/tests/doc_test/external_doc/conf.py @@ -10,11 +10,41 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "RE_", "color": "#BFD8D2", "style": "node"}, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "RE_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] test_dir = os.path.dirname(__file__) @@ -23,7 +53,11 @@ # needs_external_needs = [{"base_url": f"file://{test_dir}", "json_url": f"file://{test_json}", "id_prefix": "ext_"}] needs_external_needs = [ - {"base_url": "http://my_company.com/docs/v1/", "json_path": "needs_test_small.json", "id_prefix": "EXT_"} + { + "base_url": "http://my_company.com/docs/v1/", + "json_path": "needs_test_small.json", + "id_prefix": "EXT_", + } ] # Needed to export really ALL needs. The default entry would filter out all needs coming from external diff --git a/tests/doc_test/filter_doc/conf.py b/tests/doc_test/filter_doc/conf.py index 717640d49..787367095 100644 --- a/tests/doc_test/filter_doc/conf.py +++ b/tests/doc_test/filter_doc/conf.py @@ -8,13 +8,55 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "RE_", "color": "#BFD8D2", "style": "node"}, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, - {"directive": "user", "title": "User", "prefix": "U_", "color": "#777777", "style": "node"}, - {"directive": "action", "title": "Action", "prefix": "A_", "color": "#FFCC00", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "RE_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, + { + "directive": "user", + "title": "User", + "prefix": "U_", + "color": "#777777", + "style": "node", + }, + { + "directive": "action", + "title": "Action", + "prefix": "A_", + "color": "#FFCC00", + "style": "node", + }, ] needs_extra_links = [ diff --git a/tests/doc_test/generic_doc/conf.py b/tests/doc_test/generic_doc/conf.py index 21eab6d52..1b74e151a 100644 --- a/tests/doc_test/generic_doc/conf.py +++ b/tests/doc_test/generic_doc/conf.py @@ -1,8 +1,32 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/import_doc/conf.py b/tests/doc_test/import_doc/conf.py index fcbde4dd9..5ddaeb329 100644 --- a/tests/doc_test/import_doc/conf.py +++ b/tests/doc_test/import_doc/conf.py @@ -5,11 +5,41 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "RE_", "color": "#BFD8D2", "style": "node"}, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "RE_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_template = """ diff --git a/tests/doc_test/import_doc_empty/conf.py b/tests/doc_test/import_doc_empty/conf.py index 45270f660..7e12482c6 100644 --- a/tests/doc_test/import_doc_empty/conf.py +++ b/tests/doc_test/import_doc_empty/conf.py @@ -3,11 +3,41 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "RE_", "color": "#BFD8D2", "style": "node"}, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "RE_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_template = """ diff --git a/tests/doc_test/import_doc_invalid/conf.py b/tests/doc_test/import_doc_invalid/conf.py index 45270f660..7e12482c6 100644 --- a/tests/doc_test/import_doc_invalid/conf.py +++ b/tests/doc_test/import_doc_invalid/conf.py @@ -3,11 +3,41 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "RE_", "color": "#BFD8D2", "style": "node"}, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "RE_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_template = """ diff --git a/tests/doc_test/need_constraints/conf.py b/tests/doc_test/need_constraints/conf.py index b33483a78..ab7f10295 100644 --- a/tests/doc_test/need_constraints/conf.py +++ b/tests/doc_test/need_constraints/conf.py @@ -4,14 +4,42 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_external_needs = [ - {"base_url": "http://my_company.com/docs/v1/", "json_path": "needs_test_small.json", "id_prefix": "ext_"} + { + "base_url": "http://my_company.com/docs/v1/", + "json_path": "needs_test_small.json", + "id_prefix": "ext_", + } ] @@ -39,7 +67,11 @@ def setup(app): add_warning(app, "api_warning_filter", filter_string="status == 'example_2'") add_warning(app, "api_warning_func", custom_warning_func) - add_warning(app, "invalid_status", "status not in ['open', 'closed', 'done', 'example_2', 'example_3']") + add_warning( + app, + "invalid_status", + "status not in ['open', 'closed', 'done', 'example_2', 'example_3']", + ) # Needs option to set True or False to raise sphinx-warning for each not passed warning check diff --git a/tests/doc_test/need_constraints_failed/conf.py b/tests/doc_test/need_constraints_failed/conf.py index 31228134f..7430e40f2 100644 --- a/tests/doc_test/need_constraints_failed/conf.py +++ b/tests/doc_test/need_constraints_failed/conf.py @@ -3,14 +3,42 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_external_needs = [ - {"base_url": "http://my_company.com/docs/v1/", "json_path": "needs_test_small.json", "id_prefix": "ext_"} + { + "base_url": "http://my_company.com/docs/v1/", + "json_path": "needs_test_small.json", + "id_prefix": "ext_", + } ] @@ -38,7 +66,11 @@ def setup(app): add_warning(app, "api_warning_filter", filter_string="status == 'example_2'") add_warning(app, "api_warning_func", custom_warning_func) - add_warning(app, "invalid_status", "status not in ['open', 'closed', 'done', 'example_2', 'example_3']") + add_warning( + app, + "invalid_status", + "status not in ['open', 'closed', 'done', 'example_2', 'example_3']", + ) # Needs option to set True or False to raise sphinx-warning for each not passed warning check diff --git a/tests/doc_test/needextract_with_nested_needs/conf.py b/tests/doc_test/needextract_with_nested_needs/conf.py index df3fe57f8..7556c0c4e 100644 --- a/tests/doc_test/needextract_with_nested_needs/conf.py +++ b/tests/doc_test/needextract_with_nested_needs/conf.py @@ -3,8 +3,32 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/needpie_with_zero_needs/conf.py b/tests/doc_test/needpie_with_zero_needs/conf.py index df3fe57f8..7556c0c4e 100644 --- a/tests/doc_test/needpie_with_zero_needs/conf.py +++ b/tests/doc_test/needpie_with_zero_needs/conf.py @@ -3,8 +3,32 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/non_exists_file_import/conf.py b/tests/doc_test/non_exists_file_import/conf.py index 45270f660..7e12482c6 100644 --- a/tests/doc_test/non_exists_file_import/conf.py +++ b/tests/doc_test/non_exists_file_import/conf.py @@ -3,11 +3,41 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "RE_", "color": "#BFD8D2", "style": "node"}, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "RE_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_template = """ diff --git a/tests/doc_test/parallel_doc/conf.py b/tests/doc_test/parallel_doc/conf.py index 03f708826..f6f03d869 100644 --- a/tests/doc_test/parallel_doc/conf.py +++ b/tests/doc_test/parallel_doc/conf.py @@ -1,10 +1,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_variants = {"change_author": "assignee == 'Randy Duodu'"} needs_variant_options = ["status", "author"] diff --git a/tests/doc_test/role_need_doc/conf.py b/tests/doc_test/role_need_doc/conf.py index a3d0a4e67..b64a2a601 100644 --- a/tests/doc_test/role_need_doc/conf.py +++ b/tests/doc_test/role_need_doc/conf.py @@ -8,11 +8,41 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "req", "title": "Requirement", "prefix": "RE_", "color": "#BFD8D2", "style": "node"}, - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "req", + "title": "Requirement", + "prefix": "RE_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] test_dir = os.path.dirname(__file__) @@ -21,7 +51,11 @@ # needs_external_needs = [{"base_url": f"file://{test_dir}", "json_url": f"file://{test_json}", "id_prefix": "ext_"}] needs_external_needs = [ - {"base_url": "http://my_company.com/docs/v1/", "json_path": "needs_test_small.json", "id_prefix": "EXT_"} + { + "base_url": "http://my_company.com/docs/v1/", + "json_path": "needs_test_small.json", + "id_prefix": "EXT_", + } ] # Needed to export really ALL needs. The default entry would filter out all needs coming from external diff --git a/tests/doc_test/service_doc/conf.py b/tests/doc_test/service_doc/conf.py index b2a23705d..b931c94b1 100644 --- a/tests/doc_test/service_doc/conf.py +++ b/tests/doc_test/service_doc/conf.py @@ -3,10 +3,34 @@ extensions = ["sphinx_needs"] needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/unicode_support/conf.py b/tests/doc_test/unicode_support/conf.py index 885bd47d6..814c929f3 100644 --- a/tests/doc_test/unicode_support/conf.py +++ b/tests/doc_test/unicode_support/conf.py @@ -3,8 +3,32 @@ needs_table_style = "TABLE" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] diff --git a/tests/doc_test/variant_doc/conf.py b/tests/doc_test/variant_doc/conf.py index d94dd50ed..d78cd7913 100644 --- a/tests/doc_test/variant_doc/conf.py +++ b/tests/doc_test/variant_doc/conf.py @@ -8,10 +8,34 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_variants = {"change_author": "assignee == 'Randy Duodu'"} needs_variant_options = ["status", "author", "links"] diff --git a/tests/doc_test/variant_options/conf.py b/tests/doc_test/variant_options/conf.py index 42108d4a1..1902a3923 100644 --- a/tests/doc_test/variant_options/conf.py +++ b/tests/doc_test/variant_options/conf.py @@ -8,10 +8,34 @@ needs_id_regex = "^[A-Za-z0-9_]" needs_types = [ - {"directive": "story", "title": "User Story", "prefix": "US_", "color": "#BFD8D2", "style": "node"}, - {"directive": "spec", "title": "Specification", "prefix": "SP_", "color": "#FEDCD2", "style": "node"}, - {"directive": "impl", "title": "Implementation", "prefix": "IM_", "color": "#DF744A", "style": "node"}, - {"directive": "test", "title": "Test Case", "prefix": "TC_", "color": "#DCB239", "style": "node"}, + { + "directive": "story", + "title": "User Story", + "prefix": "US_", + "color": "#BFD8D2", + "style": "node", + }, + { + "directive": "spec", + "title": "Specification", + "prefix": "SP_", + "color": "#FEDCD2", + "style": "node", + }, + { + "directive": "impl", + "title": "Implementation", + "prefix": "IM_", + "color": "#DF744A", + "style": "node", + }, + { + "directive": "test", + "title": "Test Case", + "prefix": "TC_", + "color": "#DCB239", + "style": "node", + }, ] needs_variants = {"change_author": "assignee == 'Randy Duodu'"} needs_variant_options = [] diff --git a/tests/no_mpl_tests.py b/tests/no_mpl_tests.py index 95aaf0747..dfaeb30ef 100644 --- a/tests/no_mpl_tests.py +++ b/tests/no_mpl_tests.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needbar"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needbar"}], + indirect=True, +) def test_needbar(test_app): """Test the build fails correctly, if matplotlib is not installed.""" test_app.build() @@ -11,7 +15,11 @@ def test_needbar(test_app): assert expected in test_app._warning.getvalue() -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needpie"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needpie"}], + indirect=True, +) def test_needpie(test_app): """Test the build fails correctly, if matplotlib is not installed.""" test_app.build() diff --git a/tests/test_add_sections.py b/tests/test_add_sections.py index 77028bf84..4658beef8 100644 --- a/tests/test_add_sections.py +++ b/tests/test_add_sections.py @@ -4,7 +4,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/add_sections"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/add_sections"}], + indirect=True, +) def test_section_is_usable_in_filters(test_app): app = test_app app.builder.build_all() diff --git a/tests/test_api_configuration.py b/tests/test_api_configuration.py index 556c98887..c031f8e6e 100644 --- a/tests/test_api_configuration.py +++ b/tests/test_api_configuration.py @@ -14,7 +14,9 @@ def setup(app): sys.modules["dummy_extension.dummy"] = dummy_extension -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/api_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", [{"buildername": "html", "srcdir": "doc_test/api_doc"}], indirect=True +) def test_api_get_types(test_app): from sphinx_needs.api import get_need_types @@ -24,7 +26,11 @@ def test_api_get_types(test_app): assert set(need_types) == {"story", "spec", "impl", "test"} -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/api_doc_awesome"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/api_doc_awesome"}], + indirect=True, +) def test_api_add_type(test_app, snapshot): from sphinx_needs.api import add_need_type diff --git a/tests/test_api_usage_in_extension.py b/tests/test_api_usage_in_extension.py index 1ff0dd801..2a434e8df 100644 --- a/tests/test_api_usage_in_extension.py +++ b/tests/test_api_usage_in_extension.py @@ -22,7 +22,9 @@ def after_config(app, config): sys.modules["dummy_extension.dummy"] = dummy_extension -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/api_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", [{"buildername": "html", "srcdir": "doc_test/api_doc"}], indirect=True +) def test_api_configuration(test_app): app = test_app diff --git a/tests/test_arch.py b/tests/test_arch.py index f17ec8887..e58389a30 100644 --- a/tests/test_arch.py +++ b/tests/test_arch.py @@ -3,7 +3,9 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/arch_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", [{"buildername": "html", "srcdir": "doc_test/arch_doc"}], indirect=True +) def test_doc_build_html(test_app): app = test_app app.build() diff --git a/tests/test_basic_doc.py b/tests/test_basic_doc.py index 3c12b8ac7..806d29147 100644 --- a/tests/test_basic_doc.py +++ b/tests/test_basic_doc.py @@ -31,7 +31,9 @@ def random_data_callback(request): if re.match(r"/search/issues", request.path_url): data = GITHUB_ISSUE_SEARCH_ANSWER data["items"][0]["number"] = randrange(10000) - elif re.match(r"/.+/issue/.+", request.path_url) or re.match(r"/.+/pulls/.+", request.path_url): + elif re.match(r"/.+/issue/.+", request.path_url) or re.match( + r"/.+/pulls/.+", request.path_url + ): data = GITHUB_SPECIFIC_ISSUE_ANSWER data["number"] = randrange(10000) elif re.match(r"/search/commits", request.path_url): @@ -49,7 +51,9 @@ def random_data_callback(request): @responses.activate -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_basic"}], indirect=True) +@pytest.mark.parametrize( + "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_basic"}], indirect=True +) def test_build_html(test_app): responses.add_callback( responses.GET, @@ -57,7 +61,9 @@ def test_build_html(test_app): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) app = test_app app.builder.build_all() @@ -71,7 +77,11 @@ def test_build_html(test_app): @responses.activate -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/generic_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/generic_doc"}], + indirect=True, +) def test_build_html_parallel(test_app: Sphinx, snapshot_doctree): responses.add_callback( responses.GET, @@ -79,7 +89,9 @@ def test_build_html_parallel(test_app: Sphinx, snapshot_doctree): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) app = test_app app.builder.build_all() @@ -94,8 +106,14 @@ def test_build_html_parallel(test_app: Sphinx, snapshot_doctree): assert app.env.get_doctree("index") == snapshot_doctree -@pytest.mark.skipif(sys.platform == "win32", reason="assert fails on windows, need to fix later.") -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/generic_doc"}], indirect=True) +@pytest.mark.skipif( + sys.platform == "win32", reason="assert fails on windows, need to fix later." +) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/generic_doc"}], + indirect=True, +) def test_html_head_files(test_app): app = test_app app.builder.build_all() @@ -120,7 +138,11 @@ def test_html_head_files(test_app): @responses.activate -@pytest.mark.parametrize("test_app", [{"buildername": "singlehtml", "srcdir": "doc_test/doc_basic"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "singlehtml", "srcdir": "doc_test/doc_basic"}], + indirect=True, +) def test_build_singlehtml(test_app): responses.add_callback( responses.GET, @@ -128,14 +150,20 @@ def test_build_singlehtml(test_app): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) app = test_app app.builder.build_all() @responses.activate -@pytest.mark.parametrize("test_app", [{"buildername": "latex", "srcdir": "doc_test/doc_basic"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "latex", "srcdir": "doc_test/doc_basic"}], + indirect=True, +) def test_build_latex(test_app): responses.add_callback( responses.GET, @@ -143,14 +171,18 @@ def test_build_latex(test_app): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) app = test_app app.builder.build_all() @responses.activate -@pytest.mark.parametrize("test_app", [{"buildername": "epub", "srcdir": "doc_test/doc_basic"}], indirect=True) +@pytest.mark.parametrize( + "test_app", [{"buildername": "epub", "srcdir": "doc_test/doc_basic"}], indirect=True +) def test_build_epub(test_app): responses.add_callback( responses.GET, @@ -158,14 +190,18 @@ def test_build_epub(test_app): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) app = test_app app.builder.build_all() @responses.activate -@pytest.mark.parametrize("test_app", [{"buildername": "json", "srcdir": "doc_test/doc_basic"}], indirect=True) +@pytest.mark.parametrize( + "test_app", [{"buildername": "json", "srcdir": "doc_test/doc_basic"}], indirect=True +) def test_build_json(test_app): responses.add_callback( responses.GET, @@ -173,14 +209,20 @@ def test_build_json(test_app): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) app = test_app app.builder.build_all() @responses.activate -@pytest.mark.parametrize("test_app", [{"buildername": "needs", "srcdir": "doc_test/doc_basic"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "needs", "srcdir": "doc_test/doc_basic"}], + indirect=True, +) def test_build_needs(test_app, snapshot): responses.add_callback( responses.GET, @@ -188,7 +230,9 @@ def test_build_needs(test_app, snapshot): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) app = test_app app.builder.build_all() @@ -202,7 +246,13 @@ def test_build_needs(test_app, snapshot): @responses.activate @pytest.mark.parametrize( "test_app", - [{"buildername": "html", "srcdir": "doc_test/doc_basic", "confoverrides": {"needs_id_required": True}}], + [ + { + "buildername": "html", + "srcdir": "doc_test/doc_basic", + "confoverrides": {"needs_id_required": True}, + } + ], indirect=True, ) def test_id_required_build_html(test_app): @@ -213,7 +263,11 @@ def test_id_required_build_html(test_app): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, + re.compile(r"https://avatars.githubusercontent.com/.*"), + body="", + ) app = test_app app.builder.build_all() @@ -231,7 +285,9 @@ def test_sphinx_api_build(): callback=random_data_callback, content_type="application/json", ) - responses.add(responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="") + responses.add( + responses.GET, re.compile(r"https://avatars.githubusercontent.com/.*"), body="" + ) temp_dir = tempfile.mkdtemp() src_dir = os.path.join(os.path.dirname(__file__), "doc_test", "doc_basic") diff --git a/tests/test_broken_doc.py b/tests/test_broken_doc.py index 4458d69ce..d203541e0 100644 --- a/tests/test_broken_doc.py +++ b/tests/test_broken_doc.py @@ -3,7 +3,11 @@ from sphinx_needs.api.need import NeedsDuplicatedId -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/broken_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/broken_doc"}], + indirect=True, +) def test_doc_build_html(test_app): with pytest.raises(NeedsDuplicatedId): app = test_app diff --git a/tests/test_broken_links.py b/tests/test_broken_links.py index 0bc1613b9..37944db51 100644 --- a/tests/test_broken_links.py +++ b/tests/test_broken_links.py @@ -3,7 +3,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/broken_links", "no_plantuml": True}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/broken_links", "no_plantuml": True}], + indirect=True, ) def test_doc_build_html(test_app): app = test_app diff --git a/tests/test_broken_statuses.py b/tests/test_broken_statuses.py index dcb09237d..4efc7abff 100644 --- a/tests/test_broken_statuses.py +++ b/tests/test_broken_statuses.py @@ -3,7 +3,11 @@ from sphinx_needs.api.need import NeedsStatusNotAllowed -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/broken_statuses"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/broken_statuses"}], + indirect=True, +) def test_doc_build_html(test_app): with pytest.raises(NeedsStatusNotAllowed): app = test_app diff --git a/tests/test_broken_syntax_doc.py b/tests/test_broken_syntax_doc.py index 162da581a..33552793f 100644 --- a/tests/test_broken_syntax_doc.py +++ b/tests/test_broken_syntax_doc.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/broken_syntax_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/broken_syntax_doc"}], + indirect=True, +) def test_doc_broken_syntax(test_app): app = test_app diff --git a/tests/test_broken_tags.py b/tests/test_broken_tags.py index 8a1d6896f..631c0b623 100644 --- a/tests/test_broken_tags.py +++ b/tests/test_broken_tags.py @@ -5,7 +5,11 @@ from sphinx_needs.api.need import NeedsTagNotAllowed -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/broken_tags"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/broken_tags"}], + indirect=True, +) def test_doc_build_html(test_app): with pytest.raises(NeedsTagNotAllowed): app = test_app @@ -15,7 +19,11 @@ def test_doc_build_html(test_app): assert "SP_TOO_003" in html -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/broken_tags_2"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/broken_tags_2"}], + indirect=True, +) def test_doc_build_html_unneeded_chars(test_app): """ Test for https://github.com/useblocks/sphinxcontrib-needs/issues/36 diff --git a/tests/test_clean_log.py b/tests/test_clean_log.py index 327e8adcf..af6f25036 100644 --- a/tests/test_clean_log.py +++ b/tests/test_clean_log.py @@ -5,9 +5,13 @@ class CleanLogTestCase(unittest.TestCase): def test_external_needs_clean_log(self): - self.assertEqual(clean_log("http://user:password@host.url/"), "http://****:****@host.url/") self.assertEqual( - clean_log("Downloading file from https://daniel:my_password@server.com now"), + clean_log("http://user:password@host.url/"), "http://****:****@host.url/" + ) + self.assertEqual( + clean_log( + "Downloading file from https://daniel:my_password@server.com now" + ), "Downloading file from https://****:****@server.com now", ) self.assertEqual( diff --git a/tests/test_complex_builders.py b/tests/test_complex_builders.py index 3c913b2c7..c937df6d4 100644 --- a/tests/test_complex_builders.py +++ b/tests/test_complex_builders.py @@ -10,7 +10,14 @@ @pytest.mark.parametrize( "test_app", - [{"buildername": "latex", "srcdir": "doc_test/doc_basic_latex", "warning": True, "parallel": 2}], + [ + { + "buildername": "latex", + "srcdir": "doc_test/doc_basic_latex", + "warning": True, + "parallel": 2, + } + ], indirect=True, ) def test_doc_complex_latex(test_app): @@ -23,7 +30,14 @@ def test_doc_complex_latex(test_app): @pytest.mark.parametrize( "test_app", - [{"buildername": "singlehtml", "srcdir": "doc_test/doc_basic_latex", "warning": True, "parallel": 2}], + [ + { + "buildername": "singlehtml", + "srcdir": "doc_test/doc_basic_latex", + "warning": True, + "parallel": 2, + } + ], indirect=True, ) def test_doc_complex_singlehtml(test_app): diff --git a/tests/test_doc_build_latex.py b/tests/test_doc_build_latex.py index a8e763ee0..11b3a89e8 100644 --- a/tests/test_doc_build_latex.py +++ b/tests/test_doc_build_latex.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "latex", "srcdir": "doc_test/doc_build_latex"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "latex", "srcdir": "doc_test/doc_build_latex"}], + indirect=True, +) def test_doc_build_latex(test_app): app = test_app diff --git a/tests/test_dynamic_functions.py b/tests/test_dynamic_functions.py index 181cd2256..59d0a7978 100644 --- a/tests/test_dynamic_functions.py +++ b/tests/test_dynamic_functions.py @@ -5,7 +5,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_dynamic_functions"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_dynamic_functions"}], + indirect=True, ) def test_doc_dynamic_functions(test_app): app = test_app @@ -13,22 +15,42 @@ def test_doc_dynamic_functions(test_app): html = Path(app.outdir, "index.html").read_text() assert "This is id SP_TOO_001" in html - assert sum(1 for _ in re.finditer('test2', html)) == 2 - assert sum(1 for _ in re.finditer('test', html)) == 2 - assert sum(1 for _ in re.finditer('my_tag', html)) == 1 + assert ( + sum(1 for _ in re.finditer('test2', html)) == 2 + ) + assert ( + sum(1 for _ in re.finditer('test', html)) == 2 + ) + assert ( + sum(1 for _ in re.finditer('my_tag', html)) == 1 + ) - assert sum(1 for _ in re.finditer('test_4a', html)) == 1 - assert sum(1 for _ in re.finditer('test_4b', html)) == 1 - assert sum(1 for _ in re.finditer('TEST_4', html)) == 2 + assert ( + sum(1 for _ in re.finditer('test_4a', html)) + == 1 + ) + assert ( + sum(1 for _ in re.finditer('test_4b', html)) + == 1 + ) + assert ( + sum(1 for _ in re.finditer('TEST_4', html)) == 2 + ) - assert sum(1 for _ in re.finditer('TEST_5', html)) == 2 + assert ( + sum(1 for _ in re.finditer('TEST_5', html)) == 2 + ) assert "Test output of need TEST_3. args:" in html assert 'link' in html -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_df_calc_sum"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_df_calc_sum"}], + indirect=True, +) def test_doc_df_calc_sum(test_app): app = test_app app.build() @@ -39,7 +61,9 @@ def test_doc_df_calc_sum(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_df_check_linked_values"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_df_check_linked_values"}], + indirect=True, ) def test_doc_df_linked_values(test_app): app = test_app @@ -51,7 +75,9 @@ def test_doc_df_linked_values(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_df_user_functions"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_df_user_functions"}], + indirect=True, ) def test_doc_df_user_functions(test_app): app = test_app diff --git a/tests/test_export_id.py b/tests/test_export_id.py index dcdb7152e..19f4beccc 100644 --- a/tests/test_export_id.py +++ b/tests/test_export_id.py @@ -6,7 +6,11 @@ from syrupy.filters import props -@pytest.mark.parametrize("test_app", [{"buildername": "needs", "srcdir": "doc_test/doc_export_id"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "needs", "srcdir": "doc_test/doc_export_id"}], + indirect=True, +) def test_export_id(test_app, snapshot): app = test_app app.build() @@ -14,7 +18,11 @@ def test_export_id(test_app, snapshot): assert needs_data == snapshot(exclude=props("created")) -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_export_id"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_export_id"}], + indirect=True, +) def test_export_id_html(test_app): app = test_app app.build() diff --git a/tests/test_external.py b/tests/test_external.py index 9169cf431..de705d8e2 100644 --- a/tests/test_external.py +++ b/tests/test_external.py @@ -5,7 +5,11 @@ from syrupy.filters import props -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/external_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/external_doc"}], + indirect=True, +) def test_external_html(test_app): app = test_app app.build() @@ -17,11 +21,16 @@ def test_external_html(test_app): assert ( '

Test need ref: EXT_TEST_01

' in html + ' href="http://my_company.com/docs/v1/index.html#TEST_01">EXT_TEST_01

' + in html ) -@pytest.mark.parametrize("test_app", [{"buildername": "needs", "srcdir": "doc_test/external_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "needs", "srcdir": "doc_test/external_doc"}], + indirect=True, +) def test_external_json(test_app, snapshot): app = test_app app.build() @@ -30,7 +39,11 @@ def test_external_json(test_app, snapshot): assert needs == snapshot(exclude=props("created")) -@pytest.mark.parametrize("test_app", [{"buildername": "needs", "srcdir": "doc_test/external_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "needs", "srcdir": "doc_test/external_doc"}], + indirect=True, +) def test_external_needs_warnings(test_app): import os import subprocess @@ -40,8 +53,11 @@ def test_external_needs_warnings(test_app): srcdir = Path(app.srcdir) out_dir = os.path.join(srcdir, "_build") - out = subprocess.run(["sphinx-build", "-b", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-b", "html", srcdir, out_dir], capture_output=True + ) assert ( "WARNING: Couldn't create need EXT_TEST_03. Reason: The need-type (i.e. `ask`) is not" - " set in the project's 'need_types' configuration in conf.py." in out.stderr.decode("utf-8") + " set in the project's 'need_types' configuration in conf.py." + in out.stderr.decode("utf-8") ) diff --git a/tests/test_extra_links.py b/tests/test_extra_links.py index b57088989..e089d38f0 100644 --- a/tests/test_extra_links.py +++ b/tests/test_extra_links.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_extra_links"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_extra_links"}], + indirect=True, +) def test_extra_links_html(test_app): app = test_app app.build() @@ -16,11 +20,17 @@ def test_extra_links_html(test_app): # Check for correct dead_links handling assert 'DEAD_LINK_ALLOWED' in html - assert 'DEAD_LINK_NOT_ALLOWED' in html + assert ( + 'DEAD_LINK_NOT_ALLOWED' in html + ) assert 'REQ_005.invalid' in html -@pytest.mark.parametrize("test_app", [{"buildername": "latex", "srcdir": "doc_test/doc_extra_links"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "latex", "srcdir": "doc_test/doc_extra_links"}], + indirect=True, +) def test_extra_links_latex(test_app): app = test_app app.build() diff --git a/tests/test_extra_options.py b/tests/test_extra_options.py index 4d00b6ecc..4e6921887 100644 --- a/tests/test_extra_options.py +++ b/tests/test_extra_options.py @@ -4,7 +4,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/extra_options"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/extra_options"}], + indirect=True, +) def test_custom_attributes_appear(test_app): app = test_app app.build() @@ -37,6 +41,8 @@ def test_custom_attributes_appear(test_app): assert "R_12346" not in tables[3] # Need list should only have component B requirements - items = re.findall('(
child needs: CHILD_1_STORY
' in html_5 + 'href="#CHILD_1_STORY" title="STORY_PARENT">CHILD_1_STORY' + in html_5 ) assert ( '
parent needs: CHILD_1_STORY
' in html_5 + 'href="#CHILD_1_STORY" title="CHILD_2_STORY">CHILD_1_STORY' + in html_5 ) html_6 = Path(app.outdir, "filter_no_needs.html").read_text() diff --git a/tests/test_github_issues.py b/tests/test_github_issues.py index 717f37e5f..4c8862136 100644 --- a/tests/test_github_issues.py +++ b/tests/test_github_issues.py @@ -5,7 +5,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_github_issue_44"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_github_issue_44"}], + indirect=True, +) def test_doc_github_44(test_app): """ https://github.com/useblocks/sphinxcontrib-needs/issues/44 @@ -17,7 +21,9 @@ def test_doc_github_44(test_app): app = test_app output = subprocess.run( - ["sphinx-build", "-a", "-E", "-b", "html", app.srcdir, app.outdir], check=True, capture_output=True + ["sphinx-build", "-a", "-E", "-b", "html", app.srcdir, app.outdir], + check=True, + capture_output=True, ) # app.build() Uncomment, if build should stop on breakpoints @@ -34,7 +40,11 @@ def test_doc_github_44(test_app): ] -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_github_issue_61"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_github_issue_61"}], + indirect=True, +) def test_doc_github_61(test_app): """ Test for https://github.com/useblocks/sphinxcontrib-needs/issues/61 @@ -58,7 +68,9 @@ def test_doc_github_61(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_github_issue_160"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_github_issue_160"}], + indirect=True, ) def test_doc_github_160(test_app): app = test_app diff --git a/tests/test_global_options.py b/tests/test_global_options.py index cf45c5ab8..9829f1a7c 100644 --- a/tests/test_global_options.py +++ b/tests/test_global_options.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_global_options"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_global_options"}], + indirect=True, +) def test_doc_global_option(test_app): app = test_app app.build() diff --git a/tests/test_import.py b/tests/test_import.py index e5bd1b760..0fb73e9ad 100644 --- a/tests/test_import.py +++ b/tests/test_import.py @@ -6,7 +6,11 @@ from syrupy.filters import props -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/import_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/import_doc"}], + indirect=True, +) def test_import_json(test_app): app = test_app app.build() @@ -40,7 +44,9 @@ def test_import_json(test_app): assert "small_rel_path_TEST_01" in rel_path_import_html # Check deprecated relative path import based on conf.py - deprec_rel_path_import_html = Path(app.outdir, "subdoc/deprecated_rel_path_import.html").read_text() + deprec_rel_path_import_html = Path( + app.outdir, "subdoc/deprecated_rel_path_import.html" + ).read_text() assert "small_depr_rel_path_TEST_01" in deprec_rel_path_import_html warning = app._warning @@ -48,7 +54,11 @@ def test_import_json(test_app): assert "Deprecation warning:" in warnings -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/import_doc_invalid"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/import_doc_invalid"}], + indirect=True, +) def test_json_schema_console_check(test_app): """Checks the console output for hints about json schema validation errors""" import os @@ -58,12 +68,18 @@ def test_json_schema_console_check(test_app): srcdir = Path(app.srcdir) out_dir = os.path.join(srcdir, "_build") - out = subprocess.run(["sphinx-build", "-b", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-b", "html", srcdir, out_dir], capture_output=True + ) assert "Schema validation errors detected" in str(out.stdout) -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/import_doc_invalid"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/import_doc_invalid"}], + indirect=True, +) def test_json_schema_file_check(test_app): """Checks that an invalid json-file gets normally still imported and is used as normal (if possible)""" app = test_app @@ -74,7 +90,11 @@ def test_json_schema_file_check(test_app): assert "new_tag" in html -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/import_doc_empty"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/import_doc_empty"}], + indirect=True, +) def test_empty_file_check(test_app): """Checks that an empty needs.json throws an exception""" app = test_app @@ -85,7 +105,9 @@ def test_empty_file_check(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/non_exists_file_import"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/non_exists_file_import"}], + indirect=True, ) def test_import_non_exists_json(test_app): # Check non exists file import @@ -97,7 +119,11 @@ def test_import_non_exists_json(test_app): assert "non_exists_file_import" in err.args[0] -@pytest.mark.parametrize("test_app", [{"buildername": "needs", "srcdir": "doc_test/import_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "needs", "srcdir": "doc_test/import_doc"}], + indirect=True, +) def test_import_builder(test_app, snapshot): app = test_app app.build() @@ -107,7 +133,9 @@ def test_import_builder(test_app, snapshot): @pytest.mark.parametrize( - "test_app", [{"buildername": "needs", "srcdir": "doc_test/doc_needimport_download_needs_json"}], indirect=True + "test_app", + [{"buildername": "needs", "srcdir": "doc_test/doc_needimport_download_needs_json"}], + indirect=True, ) def test_needimport_needs_json_download(test_app, snapshot): app = test_app @@ -175,7 +203,12 @@ def test_needimport_needs_json_download(test_app, snapshot): @pytest.mark.parametrize( "test_app", - [{"buildername": "needs", "srcdir": "doc_test/doc_needimport_download_needs_json_negative"}], + [ + { + "buildername": "needs", + "srcdir": "doc_test/doc_needimport_download_needs_json_negative", + } + ], indirect=True, ) def test_needimport_needs_json_download_negative(test_app): @@ -210,11 +243,16 @@ def test_needimport_needs_json_download_negative(test_app): with requests_mock.Mocker() as m: # test with invalid url - m.get("http://my_wrong_name_company.com/docs/v1/remote-needs.json", json=remote_json) + m.get( + "http://my_wrong_name_company.com/docs/v1/remote-needs.json", + json=remote_json, + ) src_dir = Path(app.srcdir) out_dir = Path(app.outdir) - output = subprocess.run(["sphinx-build", "-M", "html", src_dir, out_dir], capture_output=True) + output = subprocess.run( + ["sphinx-build", "-M", "html", src_dir, out_dir], capture_output=True + ) assert ( "NeedimportException: Getting http://my_wrong_name_company.com/docs/v1/remote-needs.json didn't work." in output.stderr.decode("utf-8") diff --git a/tests/test_jinja_content_option.py b/tests/test_jinja_content_option.py index f9cd5f508..dbc03913e 100644 --- a/tests/test_jinja_content_option.py +++ b/tests/test_jinja_content_option.py @@ -4,7 +4,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_need_jinja_content"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_need_jinja_content"}], + indirect=True, ) def test_doc_need_jinja_content(test_app): app = test_app diff --git a/tests/test_layouts.py b/tests/test_layouts.py index 89097855f..bed530dca 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -3,7 +3,11 @@ from tests.util import extract_needs_from_html -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_layout"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_layout"}], + indirect=True, +) def test_doc_build_html(test_app): app = test_app app.build() @@ -17,7 +21,8 @@ def test_doc_build_html(test_app): assert len(needs) == 6 assert ( - 'author: some author' in html + 'author: some author' + in html ) assert '' in html diff --git a/tests/test_list2need.py b/tests/test_list2need.py index 0569c32a9..605f4331f 100644 --- a/tests/test_list2need.py +++ b/tests/test_list2need.py @@ -3,14 +3,21 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_list2need"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_list2need"}], + indirect=True, +) def test_doc_list2need_html(test_app): app = test_app app.build() index_html = Path(app.outdir, "index.html").read_text() assert "NEED-002" in index_html assert "Sub-Need on level 3" in index_html - assert 'Test chapter' in index_html + assert ( + 'Test chapter' + in index_html + ) # Check parent-child linking (nested) assert ( @@ -51,5 +58,6 @@ def test_doc_list2need_html(test_app): assert ( '
is triggered by: NEED-B
' in links_down_html + 'href="#NEED-B" title="NEED-C">NEED-B' + in links_down_html ) diff --git a/tests/test_multiple_link_backs.py b/tests/test_multiple_link_backs.py index 10516e948..2c9407918 100644 --- a/tests/test_multiple_link_backs.py +++ b/tests/test_multiple_link_backs.py @@ -4,7 +4,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/multiple_link_backs"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/multiple_link_backs"}], + indirect=True, +) def test_multiple_link_backs(test_app): app = test_app diff --git a/tests/test_need_constraints.py b/tests/test_need_constraints.py index 72e869dfa..029d2cc4f 100644 --- a/tests/test_need_constraints.py +++ b/tests/test_need_constraints.py @@ -8,7 +8,11 @@ from sphinx_needs.api.exceptions import NeedsConstraintNotAllowed -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/need_constraints"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/need_constraints"}], + indirect=True, +) def test_need_constraints(test_app, snapshot): app = test_app app.build() @@ -21,16 +25,23 @@ def test_need_constraints(test_app, snapshot): out_dir = srcdir / "_build" # Check return code when "-W --keep-going" not used - out_normal = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out_normal = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out_normal.returncode == 0 # Check return code when only "-W" is used - out_w = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir, "-W"], capture_output=True) + out_w = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir, "-W"], capture_output=True + ) assert out_w.returncode >= 1 # test if constraints_results / constraints_passed is properly set html = Path(app.outdir, "index.html").read_text() - assert "constraints_results: {'critical': {'check_0': False}}" in html + assert ( + "constraints_results: {'critical': {'check_0': False}}" + in html + ) assert 'constraints_passed: False' in html # test force_style @@ -43,7 +54,9 @@ def test_need_constraints(test_app, snapshot): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/need_constraints_failed"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/need_constraints_failed"}], + indirect=True, ) def test_need_constraints_config(test_app): app = test_app diff --git a/tests/test_need_count.py b/tests/test_need_count.py index c032460b6..7d0883d4f 100644 --- a/tests/test_need_count.py +++ b/tests/test_need_count.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_need_count"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_need_count"}], + indirect=True, +) def test_doc_need_count(test_app): app = test_app app.build() diff --git a/tests/test_need_delete_option.py b/tests/test_need_delete_option.py index 33766632a..d61ae0f09 100644 --- a/tests/test_need_delete_option.py +++ b/tests/test_need_delete_option.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_need_delete"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_need_delete"}], + indirect=True, +) def test_doc_need_delete(test_app): app = test_app app.build() diff --git a/tests/test_need_id_from_title.py b/tests/test_need_id_from_title.py index e03d20f63..077e0814b 100644 --- a/tests/test_need_id_from_title.py +++ b/tests/test_need_id_from_title.py @@ -4,7 +4,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_need_id_from_title"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_need_id_from_title"}], + indirect=True, ) def test_doc_build_html(test_app): app = test_app @@ -27,5 +29,9 @@ def test_doc_build_html(test_app): if need_type["directive"] == "story": need_directive_story_prefix = need_type["prefix"] - assert len("US_A_STORY_TITLE_2FD447") == need_id_length + len(need_directive_story_prefix) - assert len("US_CONTENT_ID_TEST_A313") == need_id_length + len(need_directive_story_prefix) + assert len("US_A_STORY_TITLE_2FD447") == need_id_length + len( + need_directive_story_prefix + ) + assert len("US_CONTENT_ID_TEST_A313") == need_id_length + len( + need_directive_story_prefix + ) diff --git a/tests/test_need_parts.py b/tests/test_need_parts.py index 09057c00a..e8a3c8c69 100644 --- a/tests/test_need_parts.py +++ b/tests/test_need_parts.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_need_parts"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_need_parts"}], + indirect=True, +) def test_doc_need_parts(test_app): app = test_app app.build() @@ -16,5 +20,7 @@ def test_doc_need_parts(test_app): assert 'exit() (SP_TOO_001.1)' in html assert 'start() (SP_TOO_001.2)' in html assert 'blub() (SP_TOO_001.awesome_id)' in html - assert 'My custom link name (SP_TOO_001.awesome_id)' in html + assert ( + 'My custom link name (SP_TOO_001.awesome_id)' in html + ) assert "SP_TOO_001" in html diff --git a/tests/test_needarch.py b/tests/test_needarch.py index b75dfab13..0d68df362 100644 --- a/tests/test_needarch.py +++ b/tests/test_needarch.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needarch"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needarch"}], + indirect=True, +) def test_doc_needarch(test_app): app = test_app app.build() @@ -12,7 +16,9 @@ def test_doc_needarch(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needarch_negative_tests"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needarch_negative_tests"}], + indirect=True, ) def test_doc_needarch_negative(test_app): import subprocess @@ -22,7 +28,9 @@ def test_doc_needarch_negative(test_app): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 1 assert ( @@ -32,7 +40,9 @@ def test_doc_needarch_negative(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needarch_jinja_func_import"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needarch_jinja_func_import"}], + indirect=True, ) def test_doc_needarch_jinja_import(test_app, snapshot): app = test_app @@ -46,7 +56,9 @@ def test_doc_needarch_jinja_import(test_app, snapshot): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needarch_jinja_func_need"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needarch_jinja_func_need"}], + indirect=True, ) def test_needarch_jinja_func_need(test_app, snapshot): app = test_app @@ -63,5 +75,7 @@ def test_needarch_jinja_func_need(test_app, snapshot): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 0 diff --git a/tests/test_needbar.py b/tests/test_needbar.py index 776b7a758..d677e7b74 100644 --- a/tests/test_needbar.py +++ b/tests/test_needbar.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needbar"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needbar"}], + indirect=True, +) def test_doc_build_html(test_app): app = test_app app.build() diff --git a/tests/test_needextend.py b/tests/test_needextend.py index c4095446f..266655c1d 100644 --- a/tests/test_needextend.py +++ b/tests/test_needextend.py @@ -7,7 +7,11 @@ from syrupy.filters import props -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needextend"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needextend"}], + indirect=True, +) def test_doc_needextend_html(test_app: Sphinx, snapshot): app = test_app app.build() @@ -20,13 +24,15 @@ def test_doc_needextend_html(test_app: Sphinx, snapshot): assert ( '
links outgoing: extend_test_004
' in index_html + 'test_004" title="extend_test_003">extend_test_004' + in index_html ) assert ( '' in index_html + 'test_004" title="extend_test_006">extend_test_004' + in index_html ) page_1__html = Path(app.outdir, "page_1.html").read_text() @@ -38,7 +44,9 @@ def test_doc_needextend_html(test_app: Sphinx, snapshot): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needextend_strict"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needextend_strict"}], + indirect=True, ) def test_doc_needextend_strict(test_app): import os @@ -49,10 +57,15 @@ def test_doc_needextend_strict(test_app): srcdir = Path(app.srcdir) out_dir = os.path.join(srcdir, "_build") - out = subprocess.run(["sphinx-build", "-b", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-b", "html", srcdir, out_dir], capture_output=True + ) # Strict option is set to false on needextend. Log info-level message - assert "Provided id strict_disable_extend_test for needextend does not exist." in out.stdout.decode("utf-8") + assert ( + "Provided id strict_disable_extend_test for needextend does not exist." + in out.stdout.decode("utf-8") + ) # Strict option is set to true on needextend. Raise Exception if sys.platform == "win32": assert ( @@ -67,7 +80,9 @@ def test_doc_needextend_strict(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needextend_dynamic"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needextend_dynamic"}], + indirect=True, ) def test_doc_needextend_dynamic(test_app, snapshot): app = test_app diff --git a/tests/test_needextract.py b/tests/test_needextract.py index 678d6f533..e0d1b40cb 100644 --- a/tests/test_needextract.py +++ b/tests/test_needextract.py @@ -4,7 +4,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needextract"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needextract"}], + indirect=True, +) def test_needextract_filter_options(test_app): import subprocess @@ -13,11 +17,17 @@ def test_needextract_filter_options(test_app): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 0 -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needextract"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needextract"}], + indirect=True, +) def test_needextract_basic_run(test_app): app = test_app app.build() @@ -28,9 +38,13 @@ def run_checks(checks, html_path): html_path = str(Path(app.outdir, html_path)) tree = html_parser.parse(html_path) for check in checks: - img_src = tree.xpath(f"//table[@id='{check[0]}']//td[@class='need content']//img/@src")[0] + img_src = tree.xpath( + f"//table[@id='{check[0]}']//td[@class='need content']//img/@src" + )[0] assert img_src == check[1] - assert os.path.exists(str(Path(app.outdir, os.path.dirname(html_path), img_src))) + assert os.path.exists( + str(Path(app.outdir, os.path.dirname(html_path), img_src)) + ) checks = [ ("US_SUB_001", "_images/smile.png"), diff --git a/tests/test_needextract_with_nested_needs.py b/tests/test_needextract_with_nested_needs.py index 5e660129c..696ef4396 100644 --- a/tests/test_needextract_with_nested_needs.py +++ b/tests/test_needextract_with_nested_needs.py @@ -4,7 +4,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/needextract_with_nested_needs"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/needextract_with_nested_needs"}], + indirect=True, ) def test_needextract_with_nested_needs(test_app): app = test_app @@ -22,9 +24,11 @@ def test_needextract_with_nested_needs(test_app): ) assert ( 'SPEC_1_1_1' in needextract_html + 'href="index.html#SPEC_1_1_1" title="SPEC_1_1_1">SPEC_1_1_1' + in needextract_html ) assert ( 'SPEC_1_1_2' in needextract_html + 'href="index.html#SPEC_1_1_2" title="SPEC_1_1_2">SPEC_1_1_2' + in needextract_html ) diff --git a/tests/test_needflow.py b/tests/test_needflow.py index 6c9ae191e..05278fe72 100644 --- a/tests/test_needflow.py +++ b/tests/test_needflow.py @@ -4,7 +4,11 @@ from docutils import __version__ as doc_ver -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needflow"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needflow"}], + indirect=True, +) def test_doc_build_html(test_app): import sphinx @@ -47,12 +51,16 @@ def test_doc_build_html(test_app): assert "STORY_2 [[../index.html#STORY_2]]" in page_html assert "STORY_2.another_one [[../index.html#STORY_2.another_one]]" in page_html - empty_needflow_with_debug = Path(app.outdir, "empty_needflow_with_debug.html").read_text() + empty_needflow_with_debug = Path( + app.outdir, "empty_needflow_with_debug.html" + ).read_text() assert "No needs passed the filters" in empty_needflow_with_debug @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needflow_incl_child_needs"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needflow_incl_child_needs"}], + indirect=True, ) def test_doc_build_needflow_incl_child_needs(test_app): app = test_app @@ -80,7 +88,9 @@ def test_doc_build_needflow_incl_child_needs(test_app): assert index_html.count("[[../index.html#SPEC_5]]") == 2 assert index_html.count("@enduml") == 1 - single_parent_need_filer_html = Path(app.outdir, "single_parent_need_filer.html").read_text() + single_parent_need_filer_html = Path( + app.outdir, "single_parent_need_filer.html" + ).read_text() assert single_parent_need_filer_html assert single_parent_need_filer_html.count("@startuml") == 1 assert single_parent_need_filer_html.count("[[../index.html#STORY_3]]") == 2 @@ -96,10 +106,14 @@ def test_doc_build_needflow_incl_child_needs(test_app): assert "[[../index.html#SPEC_4]]" not in single_parent_need_filer_html assert "[[../index.html#SPEC_5]]" not in single_parent_need_filer_html - single_child_with_child_need_filter_html = Path(app.outdir, "single_child_with_child_need_filter.html").read_text() + single_child_with_child_need_filter_html = Path( + app.outdir, "single_child_with_child_need_filter.html" + ).read_text() assert single_child_with_child_need_filter_html assert single_child_with_child_need_filter_html.count("@startuml") == 1 - assert single_child_with_child_need_filter_html.count("[[../index.html#STORY_2]]") == 2 + assert ( + single_child_with_child_need_filter_html.count("[[../index.html#STORY_2]]") == 2 + ) assert single_child_with_child_need_filter_html.count("@enduml") == 1 assert "[[../index.html#STORY_1]]" not in single_child_with_child_need_filter_html assert "[[../index.html#STORY_1.1]]" not in single_child_with_child_need_filter_html @@ -112,7 +126,9 @@ def test_doc_build_needflow_incl_child_needs(test_app): assert "[[../index.html#STORY_3]]" not in single_child_with_child_need_filter_html assert "[[../index.html#SPEC_5]]" not in single_child_with_child_need_filter_html - single_child_need_filter_html = Path(app.outdir, "single_child_need_filter.html").read_text() + single_child_need_filter_html = Path( + app.outdir, "single_child_need_filter.html" + ).read_text() assert single_child_need_filter_html assert single_child_need_filter_html.count("@startuml") == 1 assert single_child_need_filter_html.count("[[../index.html#SPEC_1]]") == 2 diff --git a/tests/test_needimport_noindex.py b/tests/test_needimport_noindex.py index dd1312af5..b6aaacf87 100644 --- a/tests/test_needimport_noindex.py +++ b/tests/test_needimport_noindex.py @@ -6,7 +6,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "latex", "srcdir": "doc_test/doc_needimport_noindex"}], indirect=True + "test_app", + [{"buildername": "latex", "srcdir": "doc_test/doc_needimport_noindex"}], + indirect=True, ) def test_doc_needimport_noindex(test_app): app = test_app @@ -17,5 +19,5 @@ def test_doc_needimport_noindex(test_app): print(f"in path {app.outdir}", sys.stderr) assert os.path.exists(latex_path) - assert 0 < len(latex) + assert len(latex) > 0 assert "AAA" in latex diff --git a/tests/test_needlist.py b/tests/test_needlist.py index 1436bf118..eafec6308 100644 --- a/tests/test_needlist.py +++ b/tests/test_needlist.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needlist"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needlist"}], + indirect=True, +) def test_doc_build_html(test_app): app = test_app app.build() diff --git a/tests/test_needpie.py b/tests/test_needpie.py index 3e33ad8dc..4bcaa20c4 100644 --- a/tests/test_needpie.py +++ b/tests/test_needpie.py @@ -7,7 +7,11 @@ import sphinx -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needpie"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needpie"}], + indirect=True, +) def test_doc_build_html(test_app): app = test_app app.build() diff --git a/tests/test_needpie_with_zero_needs.py b/tests/test_needpie_with_zero_needs.py index 44e9a012b..b775237ed 100644 --- a/tests/test_needpie_with_zero_needs.py +++ b/tests/test_needpie_with_zero_needs.py @@ -2,7 +2,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/needpie_with_zero_needs"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/needpie_with_zero_needs"}], + indirect=True, ) def test_needpie_with_zero_needs(test_app): app = test_app diff --git a/tests/test_needreport.py b/tests/test_needreport.py index 73c474fec..8efef1a84 100644 --- a/tests/test_needreport.py +++ b/tests/test_needreport.py @@ -3,13 +3,20 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needreport"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needreport"}], + indirect=True, +) def test_doc_needarch(test_app): app = test_app app.build() # check for warning about missing options warnings = app._warning.getvalue() - assert "index.rst:6: WARNING: No options specified to generate need report [needs.report]" in warnings + assert ( + "index.rst:6: WARNING: No options specified to generate need report [needs.report]" + in warnings + ) assert "index.rst:8: WARNING: Could not load needs report template file" in warnings html = Path(app.outdir, "index.html").read_text(encoding="utf8") assert "Need Types" in html diff --git a/tests/test_needs_builder.py b/tests/test_needs_builder.py index 06e9dbbca..61fa2c1d5 100644 --- a/tests/test_needs_builder.py +++ b/tests/test_needs_builder.py @@ -7,7 +7,11 @@ from syrupy.filters import props -@pytest.mark.parametrize("test_app", [{"buildername": "needs", "srcdir": "doc_test/doc_needs_builder"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "needs", "srcdir": "doc_test/doc_needs_builder"}], + indirect=True, +) def test_doc_needs_builder(test_app, snapshot): app = test_app app.build() @@ -36,7 +40,9 @@ def test_doc_needs_builder_reproducible(test_app, snapshot): @pytest.mark.parametrize( - "test_app", [{"buildername": "needs", "srcdir": "doc_test/doc_needs_builder_negative_tests"}], indirect=True + "test_app", + [{"buildername": "needs", "srcdir": "doc_test/doc_needs_builder_negative_tests"}], + indirect=True, ) def test_doc_needs_build_without_needs_file(test_app): app = test_app @@ -44,13 +50,20 @@ def test_doc_needs_build_without_needs_file(test_app): srcdir = Path(app.srcdir) out_dir = os.path.join(srcdir, "_build") - out = subprocess.run(["sphinx-build", "-b", "needs", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-b", "needs", srcdir, out_dir], capture_output=True + ) assert not out.stderr - assert "needs.json found, but will not be used because needs_file not configured." in out.stdout.decode("utf-8") + assert ( + "needs.json found, but will not be used because needs_file not configured." + in out.stdout.decode("utf-8") + ) @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needs_builder_parallel"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needs_builder_parallel"}], + indirect=True, ) def test_needs_html_and_json(test_app): """ @@ -64,7 +77,9 @@ def test_needs_html_and_json(test_app): srcdir = app.srcdir build_dir = os.path.join(app.outdir, "../needs") - subprocess.run(["sphinx-build", "-b", "needs", srcdir, build_dir], capture_output=True) + subprocess.run( + ["sphinx-build", "-b", "needs", srcdir, build_dir], capture_output=True + ) needs_json_path_2 = os.path.join(build_dir, "needs.json") assert os.path.exists(needs_json_path_2) diff --git a/tests/test_needs_external_needs_build.py b/tests/test_needs_external_needs_build.py index a5a4ad0a8..0ba7c4d34 100644 --- a/tests/test_needs_external_needs_build.py +++ b/tests/test_needs_external_needs_build.py @@ -9,7 +9,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needs_external_needs"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needs_external_needs"}], + indirect=True, ) def test_doc_build_html(test_app, sphinx_test_tempdir): import subprocess @@ -18,9 +20,12 @@ def test_doc_build_html(test_app, sphinx_test_tempdir): src_dir = Path(app.srcdir) out_dir = Path(app.outdir) - plantuml = r"java -Djava.awt.headless=true -jar %s" % os.path.join(sphinx_test_tempdir, "utils", "plantuml.jar") + plantuml = r"java -Djava.awt.headless=true -jar %s" % os.path.join( + sphinx_test_tempdir, "utils", "plantuml.jar" + ) output = subprocess.run( - ["sphinx-build", "-b", "html", "-D", rf"plantuml={plantuml}", src_dir, out_dir], capture_output=True + ["sphinx-build", "-b", "html", "-D", rf"plantuml={plantuml}", src_dir, out_dir], + capture_output=True, ) assert output.stderr.decode("utf-8").splitlines() == [ "WARNING: http://my_company.com/docs/v1/index.html#TEST_01: Need 'EXT_TEST_01' has unknown outgoing link 'SPEC_1' in field 'links' [needs.external_link_outgoing]", @@ -29,24 +34,36 @@ def test_doc_build_html(test_app, sphinx_test_tempdir): # run second time and check output_second = subprocess.run( - ["sphinx-build", "-b", "html", "-D", rf"plantuml={plantuml}", src_dir, out_dir], capture_output=True + ["sphinx-build", "-b", "html", "-D", rf"plantuml={plantuml}", src_dir, out_dir], + capture_output=True, ) assert not output_second.stderr # check if incremental build used # first build output - assert "updating environment: [new config] 3 added, 0 changed, 0 removed" in output.stdout.decode("utf-8") + assert ( + "updating environment: [new config] 3 added, 0 changed, 0 removed" + in output.stdout.decode("utf-8") + ) # second build output assert "loading pickled environment" in output_second.stdout.decode("utf-8") - assert "updating environment: [new config] 3 added, 0 changed, 0 removed" not in output_second.stdout.decode( - "utf-8" + assert ( + "updating environment: [new config] 3 added, 0 changed, 0 removed" + not in output_second.stdout.decode("utf-8") + ) + assert ( + "updating environment: 0 added, 0 changed, 0 removed" + in output_second.stdout.decode("utf-8") ) - assert "updating environment: 0 added, 0 changed, 0 removed" in output_second.stdout.decode("utf-8") -@pytest.mark.skipif(sys.platform == "win32", reason="assert fails on windows, need to fix later.") +@pytest.mark.skipif( + sys.platform == "win32", reason="assert fails on windows, need to fix later." +) @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needs_external_needs"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needs_external_needs"}], + indirect=True, ) def test_external_needs_base_url_relative_path(test_app): app = test_app @@ -75,7 +92,10 @@ def test_external_needs_base_url_relative_path(test_app): assert root_list_hrefs[4].attrib["href"] == "../../_build/html/index.html#TEST_02" assert root_list_hrefs[4].text == "EXT_REL_PATH_TEST_02: TEST_02 DESCRIPTION" # check base_url url - assert root_list_hrefs[1].attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_02" + assert ( + root_list_hrefs[1].attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_02" + ) assert root_list_hrefs[1].text == "EXT_TEST_02: TEST_02 DESCRIPTION" # check needtable usage for base_url in root level @@ -87,30 +107,48 @@ def test_external_needs_base_url_relative_path(test_app): assert root_table_hrefs[0].attrib["href"] == "../../_build/html/index.html#TEST_01" assert root_table_hrefs[0].text == "EXT_REL_PATH_TEST_01" # check base_url url in root level - assert root_table_hrefs[4].attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_01" + assert ( + root_table_hrefs[4].attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_01" + ) assert root_table_hrefs[4].text == "EXT_TEST_01" # check needflow usage for base_url in root level if not sphinx.__version__.startswith("3.5"): if int(doc_ver.split(".")[1]) >= 18: root_flow_hrefs = root_tree.xpath("//figure/p/object/a/img") - assert root_tree.xpath("//figure/figcaption/p/span/a")[0].text == "My needflow" + assert ( + root_tree.xpath("//figure/figcaption/p/span/a")[0].text == "My needflow" + ) else: - root_flow_hrefs = root_tree.xpath("//div[@class='figure align-center']/p/object/a/img") + root_flow_hrefs = root_tree.xpath( + "//div[@class='figure align-center']/p/object/a/img" + ) assert ( - root_tree.xpath("//div[@class='figure align-center']/p[@class='caption']/span/a")[0].text + root_tree.xpath( + "//div[@class='figure align-center']/p[@class='caption']/span/a" + )[0].text == "My needflow" ) # check base_url url in root level - assert "as EXT_TEST_01 [[http://my_company.com/docs/v1/index.html#TEST_01]]" in root_flow_hrefs[0].attrib["alt"] + assert ( + "as EXT_TEST_01 [[http://my_company.com/docs/v1/index.html#TEST_01]]" + in root_flow_hrefs[0].attrib["alt"] + ) # check base_url relative path in root level - assert "as EXT_REL_PATH_TEST_01 [[../../../_build/html/index.html#TEST_01]]" in root_flow_hrefs[0].attrib["alt"] + assert ( + "as EXT_REL_PATH_TEST_01 [[../../../_build/html/index.html#TEST_01]]" + in root_flow_hrefs[0].attrib["alt"] + ) # check role need_outgoing and need_incoming for base_url in root level for element in root_tree.xpath("//p/span/a"): # check link for need_outgoing if element.text == "EXT_TEST_01": - assert element.attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_01" + assert ( + element.attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_01" + ) # check link for need_incoming if element.text == "EXT_REL_PATH_TEST_02": assert element.attrib["href"] == "../../_build/html/index.html#TEST_02" @@ -128,7 +166,10 @@ def test_external_needs_base_url_relative_path(test_app): assert sub_list_hrefs[3].attrib["href"] == "../../../_build/html/index.html#TEST_01" assert sub_list_hrefs[3].text == "EXT_REL_PATH_TEST_01: TEST_01 DESCRIPTION" # check base_url url in subfolder level - assert sub_list_hrefs[0].attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_01" + assert ( + sub_list_hrefs[0].attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_01" + ) assert sub_list_hrefs[0].text == "EXT_TEST_01: TEST_01 DESCRIPTION" # check needtable usage for base_url in subfolder level @@ -137,39 +178,61 @@ def test_external_needs_base_url_relative_path(test_app): if "class" in external_link.attrib: assert external_link.attrib["class"] == "external_link reference external" # check base_url relative path in subfolder level, one level deeper than base_url - assert sub_table_hrefs[0].attrib["href"] == "../../../_build/html/index.html#TEST_01" + assert ( + sub_table_hrefs[0].attrib["href"] == "../../../_build/html/index.html#TEST_01" + ) assert sub_table_hrefs[0].text == "EXT_REL_PATH_TEST_01" # check base_url url in subfolder level - assert sub_table_hrefs[4].attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_01" + assert ( + sub_table_hrefs[4].attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_01" + ) assert sub_table_hrefs[4].text == "EXT_TEST_01" # check needflow usage for base_url in subfolder level if not sphinx.__version__.startswith("3.5"): if int(doc_ver.split(".")[1]) >= 18: sub_flow_hrefs = sub_tree.xpath("//figure/p/object/a/img") - assert sub_tree.xpath("//figure/figcaption/p/span/a")[0].text == "My needflow" + assert ( + sub_tree.xpath("//figure/figcaption/p/span/a")[0].text == "My needflow" + ) else: - sub_flow_hrefs = sub_tree.xpath("//div[@class='figure align-center']/p/object/a/img") + sub_flow_hrefs = sub_tree.xpath( + "//div[@class='figure align-center']/p/object/a/img" + ) assert ( - sub_tree.xpath("//div[@class='figure align-center']/p[@class='caption']/span/a")[0].text + sub_tree.xpath( + "//div[@class='figure align-center']/p[@class='caption']/span/a" + )[0].text == "My needflow" ) # check base_url url in root level - assert "as EXT_TEST_01 [[http://my_company.com/docs/v1/index.html#TEST_01]]" in sub_flow_hrefs[0].attrib["alt"] + assert ( + "as EXT_TEST_01 [[http://my_company.com/docs/v1/index.html#TEST_01]]" + in sub_flow_hrefs[0].attrib["alt"] + ) # check base_url relative path in subfolder level, one level deeper than base_url - assert "as EXT_REL_PATH_TEST_01 [[../../../_build/html/index.html#TEST_01]]" in sub_flow_hrefs[0].attrib["alt"] + assert ( + "as EXT_REL_PATH_TEST_01 [[../../../_build/html/index.html#TEST_01]]" + in sub_flow_hrefs[0].attrib["alt"] + ) # check role need_outgoing and need_incoming for base_url in subfolder level for element in sub_tree.xpath("//p/span/a"): # check link for need_outgoing if element.text == "EXT_TEST_01": - assert element.attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_01" + assert ( + element.attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_01" + ) # check link for need_incoming if element.text == "EXT_REL_PATH_TEST_02": assert element.attrib["href"] == "../../../_build/html/index.html#TEST_02" # check usage in sub subfolder level - sub_sub_html_path = str(Path(app.outdir, "subfolder_b", "subfolder_c", "index.html")) + sub_sub_html_path = str( + Path(app.outdir, "subfolder_b", "subfolder_c", "index.html") + ) sub_sub_tree = html_parser.parse(sub_sub_html_path) # check needlist usage for base_url in subsubfolder level @@ -178,10 +241,16 @@ def test_external_needs_base_url_relative_path(test_app): if "class" in ext_link.attrib: assert ext_link.attrib["class"] == "external_link reference external" # check base_url relative path in subsubfolder level, two level deeper than base_url - assert sub_sub_list_hrefs[3].attrib["href"] == "../../../../_build/html/index.html#TEST_01" + assert ( + sub_sub_list_hrefs[3].attrib["href"] + == "../../../../_build/html/index.html#TEST_01" + ) assert sub_sub_list_hrefs[3].text == "EXT_REL_PATH_TEST_01: TEST_01 DESCRIPTION" # check base_url url in subsubfolder level - assert sub_sub_list_hrefs[0].attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_01" + assert ( + sub_sub_list_hrefs[0].attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_01" + ) assert sub_sub_list_hrefs[0].text == "EXT_TEST_01: TEST_01 DESCRIPTION" # check needtable usage for base_url in subsubfolder level @@ -190,45 +259,67 @@ def test_external_needs_base_url_relative_path(test_app): if "class" in external_link.attrib: assert external_link.attrib["class"] == "external_link reference external" # check base_url relative path in subsubfolder level, two level deeper than base_url - assert sub_sub_table_hrefs[0].attrib["href"] == "../../../../_build/html/index.html#TEST_01" + assert ( + sub_sub_table_hrefs[0].attrib["href"] + == "../../../../_build/html/index.html#TEST_01" + ) assert sub_sub_table_hrefs[0].text == "EXT_REL_PATH_TEST_01" # check base_url url in subsubfolder level - assert sub_sub_table_hrefs[4].attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_01" + assert ( + sub_sub_table_hrefs[4].attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_01" + ) assert sub_sub_table_hrefs[4].text == "EXT_TEST_01" # check needflow usage for base_url in subsubfolder level if not sphinx.__version__.startswith("3.5"): if int(doc_ver.split(".")[1]) >= 18: sub_sub_flow_hrefs = sub_sub_tree.xpath("//figure/p/object/a/img") - assert sub_sub_tree.xpath("//figure/figcaption/p/span/a")[0].text == "My needflow" + assert ( + sub_sub_tree.xpath("//figure/figcaption/p/span/a")[0].text + == "My needflow" + ) else: - sub_sub_flow_hrefs = sub_tree.xpath("//div[@class='figure align-center']/p/object/a/img") + sub_sub_flow_hrefs = sub_tree.xpath( + "//div[@class='figure align-center']/p/object/a/img" + ) assert ( - sub_sub_tree.xpath("//div[@class='figure align-center']/p[@class='caption']/span/a")[0].text + sub_sub_tree.xpath( + "//div[@class='figure align-center']/p[@class='caption']/span/a" + )[0].text == "My needflow" ) # check base_url url in subsubfolder level assert ( - "as EXT_TEST_01 [[http://my_company.com/docs/v1/index.html#TEST_01]]" in sub_sub_flow_hrefs[0].attrib["alt"] + "as EXT_TEST_01 [[http://my_company.com/docs/v1/index.html#TEST_01]]" + in sub_sub_flow_hrefs[0].attrib["alt"] ) # check base_url relative path in subsubfolder level, two level deeper than base_url assert ( - "as EXT_REL_PATH_TEST_01 [[../../../_build/html/index.html#TEST_01]]" in sub_sub_flow_hrefs[0].attrib["alt"] + "as EXT_REL_PATH_TEST_01 [[../../../_build/html/index.html#TEST_01]]" + in sub_sub_flow_hrefs[0].attrib["alt"] ) # check role need_outgoing and need_incoming for base_url in subsubfolder level for element in sub_sub_tree.xpath("//p/span/a"): # check link for need_outgoing if element.text == "EXT_TEST_01": - assert element.attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_01" + assert ( + element.attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_01" + ) # check link for need_incoming if element.text == "EXT_REL_PATH_TEST_02": - assert element.attrib["href"] == "../../../../_build/html/index.html#TEST_02" + assert ( + element.attrib["href"] == "../../../../_build/html/index.html#TEST_02" + ) @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needs_external_needs_remote"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needs_external_needs_remote"}], + indirect=True, ) def test_external_needs_json_url(test_app): app = test_app @@ -283,7 +374,10 @@ def test_external_needs_json_url(test_app): if "class" in ext_link.attrib: assert ext_link.attrib["class"] == "external_link reference external" # check usage from remote URL - assert root_list_hrefs[0].attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_101" + assert ( + root_list_hrefs[0].attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_101" + ) assert root_list_hrefs[0].text == "EXT_REMOTE_TEST_101: TEST_101 TITLE" # check needtable usage for base_url in root level @@ -292,12 +386,22 @@ def test_external_needs_json_url(test_app): if "class" in external_link.attrib: assert external_link.attrib["class"] == "external_link reference external" # check for remote url - assert root_table_hrefs[0].attrib["href"] == "http://my_company.com/docs/v1/index.html#TEST_101" + assert ( + root_table_hrefs[0].attrib["href"] + == "http://my_company.com/docs/v1/index.html#TEST_101" + ) assert root_table_hrefs[0].text == "EXT_REMOTE_TEST_101" @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needs_external_needs_with_target_url"}], indirect=True + "test_app", + [ + { + "buildername": "html", + "srcdir": "doc_test/doc_needs_external_needs_with_target_url", + } + ], + indirect=True, ) def test_external_needs_target_url(test_app): app = test_app diff --git a/tests/test_needs_filter_data.py b/tests/test_needs_filter_data.py index ff1c4f710..bf1fee904 100644 --- a/tests/test_needs_filter_data.py +++ b/tests/test_needs_filter_data.py @@ -5,7 +5,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needs_filter_data"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needs_filter_data"}], + indirect=True, ) def test_doc_needs_filter_data_html(test_app): app = test_app @@ -29,7 +31,10 @@ def test_doc_needs_filter_data_html(test_app): # Check needtable works assert 'Example table' in index_html assert '

Test Example 3

' in index_html - assert '

my_tag; current_variant

' in index_html + assert ( + '

my_tag; current_variant

' + in index_html + ) # check needflow works if int(doc_ver.split(".")[1]) >= 18: @@ -48,7 +53,8 @@ def test_doc_needs_filter_data_html(test_app): assert ( 'tags: ' 'test_tag_001' - ', current_variant' in index_html + ', current_variant' + in index_html ) # check needs_warnings works @@ -62,7 +68,9 @@ def test_doc_needs_filter_data_html(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needs_filter_data"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needs_filter_data"}], + indirect=True, ) def test_doc_needs_filter_code(test_app): app = test_app diff --git a/tests/test_needs_id_builder.py b/tests/test_needs_id_builder.py index 6c647242b..cca0c9ef7 100644 --- a/tests/test_needs_id_builder.py +++ b/tests/test_needs_id_builder.py @@ -9,7 +9,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "needs_id", "srcdir": "doc_test/doc_needs_builder"}], indirect=True + "test_app", + [{"buildername": "needs_id", "srcdir": "doc_test/doc_needs_builder"}], + indirect=True, ) def test_doc_needs_id_builder(test_app, snapshot): app = test_app @@ -17,5 +19,7 @@ def test_doc_needs_id_builder(test_app, snapshot): data = SphinxNeedsData(app.env) needs_config = NeedsSphinxConfig(app.config) needs_id_path = Path(app.outdir, needs_config.build_json_per_id_path) - data = {path.name: json.loads(path.read_text()) for path in needs_id_path.glob("*.json")} + data = { + path.name: json.loads(path.read_text()) for path in needs_id_path.glob("*.json") + } assert data == snapshot(exclude=props("created")) diff --git a/tests/test_needs_warning.py b/tests/test_needs_warning.py index 3a4f03411..866d9bab1 100644 --- a/tests/test_needs_warning.py +++ b/tests/test_needs_warning.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needs_warnings"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needs_warnings"}], + indirect=True, +) def test_needs_warnings(test_app): app = test_app app.build() @@ -18,7 +22,10 @@ def test_needs_warnings(test_app): # check warnings contents assert "WARNING: invalid_status: failed" in warnings assert "failed needs: 2 (SP_TOO_001, US_63252)" in warnings - assert "used filter: status not in ['open', 'closed', 'done', 'example_2', 'example_3']" in warnings + assert ( + "used filter: status not in ['open', 'closed', 'done', 'example_2', 'example_3']" + in warnings + ) # check needs warning from custom defined filter code assert "failed needs: 1 (TC_001)" in warnings @@ -36,7 +43,14 @@ def test_needs_warnings(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needs_warnings_return_status_code"}], indirect=True + "test_app", + [ + { + "buildername": "html", + "srcdir": "doc_test/doc_needs_warnings_return_status_code", + } + ], + indirect=True, ) def test_needs_warnings_return_status_code(test_app): import subprocess @@ -47,22 +61,28 @@ def test_needs_warnings_return_status_code(test_app): out_dir = srcdir / "_build" # Check return code when "-W --keep-going" not used - out_normal = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out_normal = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out_normal.returncode == 0 # Check return code when only "-W" is used - out_w = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir, "-W"], capture_output=True) + out_w = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir, "-W"], capture_output=True + ) assert out_w.returncode >= 1 # Check return code when only "--keep-going" is used out_keep_going = subprocess.run( - ["sphinx-build", "-M", "html", srcdir, out_dir, "--keep-going"], capture_output=True + ["sphinx-build", "-M", "html", srcdir, out_dir, "--keep-going"], + capture_output=True, ) assert out_keep_going.returncode == 0 # Check return code when "-W --keep-going" is used out_w_keep_going = subprocess.run( - ["sphinx-build", "-M", "html", srcdir, out_dir, "-W", "--keep-going"], capture_output=True + ["sphinx-build", "-M", "html", srcdir, out_dir, "-W", "--keep-going"], + capture_output=True, ) assert out_w_keep_going.returncode == 1 @@ -77,7 +97,10 @@ def test_needs_warnings_return_status_code(test_app): # Check warnings contents assert "WARNING: invalid_status: failed" in warnings assert "failed needs: 2 (SP_TOO_001, US_63252)" in warnings - assert "used filter: status not in ['open', 'closed', 'done', 'example_2', 'example_3']" in warnings + assert ( + "used filter: status not in ['open', 'closed', 'done', 'example_2', 'example_3']" + in warnings + ) # Check needs warning from custom defined filter code assert "WARNING: type_match: failed" in warnings diff --git a/tests/test_needsfile.py b/tests/test_needsfile.py index 5bcae3149..d5a24f35c 100644 --- a/tests/test_needsfile.py +++ b/tests/test_needsfile.py @@ -1,7 +1,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "needs", "srcdir": "doc_test/doc_needsfile"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "needs", "srcdir": "doc_test/doc_needsfile"}], + indirect=True, +) def test_doc_build_html(test_app): app = test_app app.build() diff --git a/tests/test_needtable.py b/tests/test_needtable.py index 211be333e..cdbed2296 100644 --- a/tests/test_needtable.py +++ b/tests/test_needtable.py @@ -4,7 +4,11 @@ from docutils import __version__ as doc_ver -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needtable"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needtable"}], + indirect=True, +) def test_doc_build_html(test_app): app = test_app app.build() @@ -59,7 +63,11 @@ def test_doc_build_html(test_app): assert '' in colwidths_html_path -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needtable"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needtable"}], + indirect=True, +) def test_doc_needtable_options(test_app): import sphinx @@ -121,7 +129,11 @@ def test_doc_needtable_options(test_app): assert string_column_order in html -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needtable"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needtable"}], + indirect=True, +) def test_doc_needtable_styles(test_app): app = test_app app.build() @@ -131,7 +143,11 @@ def test_doc_needtable_styles(test_app): assert "NEEDS_DATATABLES" in html -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needtable"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needtable"}], + indirect=True, +) def test_doc_needtable_parts(test_app): app = test_app app.build() @@ -142,7 +158,11 @@ def test_doc_needtable_parts(test_app): assert 'class="need_part' in html -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needtable"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needtable"}], + indirect=True, +) def test_doc_needtable_titles(test_app): app = test_app app.build() diff --git a/tests/test_needuml.py b/tests/test_needuml.py index 45a0f518b..4beb42f9a 100644 --- a/tests/test_needuml.py +++ b/tests/test_needuml.py @@ -5,7 +5,11 @@ from syrupy.filters import props -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needuml"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needuml"}], + indirect=True, +) def test_doc_build_html(test_app, snapshot): app = test_app app.build() @@ -20,7 +24,9 @@ def test_doc_build_html(test_app, snapshot): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needuml_duplicate_key"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needuml_duplicate_key"}], + indirect=True, ) def test_needuml_option_key_duplicate(test_app): app = test_app @@ -28,17 +34,22 @@ def test_needuml_option_key_duplicate(test_app): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 1 assert ( "sphinx_needs.directives.needuml.NeedumlException: Inside need: INT_001, " - "found duplicate Needuml option key name: sequence" in out.stderr.decode("utf-8") + "found duplicate Needuml option key name: sequence" + in out.stderr.decode("utf-8") ) @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needuml_key_name_diagram"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needuml_key_name_diagram"}], + indirect=True, ) def test_needuml_option_key_forbidden(test_app): app = test_app @@ -46,7 +57,9 @@ def test_needuml_option_key_forbidden(test_app): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 1 assert ( @@ -56,7 +69,9 @@ def test_needuml_option_key_forbidden(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needuml_diagram_allowmixing"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needuml_diagram_allowmixing"}], + indirect=True, ) def test_needuml_diagram_allowmixing(test_app): app = test_app @@ -64,11 +79,17 @@ def test_needuml_diagram_allowmixing(test_app): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 0 -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needuml_save"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needuml_save"}], + indirect=True, +) def test_needuml_save(test_app, snapshot): app = test_app app.build() @@ -91,7 +112,9 @@ def test_needuml_save(test_app, snapshot): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needuml_save_with_abs_path"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needuml_save_with_abs_path"}], + indirect=True, ) def test_needuml_save_with_abs_path(test_app): app = test_app @@ -99,17 +122,22 @@ def test_needuml_save_with_abs_path(test_app): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 1 assert ( "sphinx_needs.directives.needuml.NeedumlException: " - "Given save path: /_out/my_needuml.puml, is not a relative path." in out.stderr.decode("utf-8") + "Given save path: /_out/my_needuml.puml, is not a relative path." + in out.stderr.decode("utf-8") ) @pytest.mark.parametrize( - "test_app", [{"buildername": "needumls", "srcdir": "doc_test/doc_needuml_save"}], indirect=True + "test_app", + [{"buildername": "needumls", "srcdir": "doc_test/doc_needuml_save"}], + indirect=True, ) def test_needumls_builder(test_app, snapshot): app = test_app @@ -131,7 +159,11 @@ def test_needumls_builder(test_app, snapshot): assert umls == snapshot -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needuml_filter"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needuml_filter"}], + indirect=True, +) def test_needuml_filter(test_app, snapshot): app = test_app app.build() @@ -145,12 +177,16 @@ def test_needuml_filter(test_app, snapshot): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 0 @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needuml_jinja_func_flow"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needuml_jinja_func_flow"}], + indirect=True, ) def test_needuml_jinja_func_flow(test_app, snapshot): app = test_app @@ -165,12 +201,16 @@ def test_needuml_jinja_func_flow(test_app, snapshot): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 0 @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needuml_jinja_func_need_removed"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needuml_jinja_func_need_removed"}], + indirect=True, ) def test_needuml_jinja_func_need_removed(test_app): app = test_app @@ -178,17 +218,25 @@ def test_needuml_jinja_func_need_removed(test_app): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 1 assert ( "sphinx_needs.directives.needuml.NeedumlException: " - "Jinja function 'need()' is not supported in needuml directive." in out.stderr.decode("utf-8") + "Jinja function 'need()' is not supported in needuml directive." + in out.stderr.decode("utf-8") ) @pytest.mark.parametrize( "test_app", - [{"buildername": "html", "srcdir": "doc_test/doc_needuml_jinja_func_import_negative_tests"}], + [ + { + "buildername": "html", + "srcdir": "doc_test/doc_needuml_jinja_func_import_negative_tests", + } + ], indirect=True, ) def test_doc_needarch_jinja_import_negative(test_app): @@ -197,17 +245,22 @@ def test_doc_needarch_jinja_import_negative(test_app): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 1 assert ( "sphinx_needs.directives.needuml.NeedumlException: " - "Jinja function 'import()' is not supported in needuml directive." in out.stderr.decode("utf-8") + "Jinja function 'import()' is not supported in needuml directive." + in out.stderr.decode("utf-8") ) @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needuml_jinja_func_ref"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_needuml_jinja_func_ref"}], + indirect=True, ) def test_needuml_jinja_func_ref(test_app, snapshot): app = test_app @@ -223,5 +276,7 @@ def test_needuml_jinja_func_ref(test_app, snapshot): srcdir = Path(app.srcdir) out_dir = srcdir / "_build" - out = subprocess.run(["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True) + out = subprocess.run( + ["sphinx-build", "-M", "html", srcdir, out_dir], capture_output=True + ) assert out.returncode == 0 diff --git a/tests/test_open_needs_service.py b/tests/test_open_needs_service.py index da2cd1564..e88a2e1da 100644 --- a/tests/test_open_needs_service.py +++ b/tests/test_open_needs_service.py @@ -22,7 +22,12 @@ def json(): "description": "We finally need to build our Neptune3000 rocket.", "format": "txt", "project_id": 1, - "options": {"status": "done", "priority": "high", "costs": 3500000, "approved": 1}, + "options": { + "status": "done", + "priority": "high", + "costs": 3500000, + "approved": 1, + }, "references": {}, }, { @@ -32,7 +37,12 @@ def json(): "description": "Lets test the rocket on a test bench", "format": "txt", "project_id": 1, - "options": {"status": "open", "priority": "high", "costs": 500000, "approved": 0}, + "options": { + "status": "open", + "priority": "high", + "costs": 500000, + "approved": 0, + }, "references": {}, }, { @@ -42,7 +52,12 @@ def json(): "description": "Red and blue. No other colors please.", "format": "txt", "project_id": 1, - "options": {"status": "open", "priority": "low", "costs": 20000, "approved": 1}, + "options": { + "status": "open", + "priority": "low", + "costs": 20000, + "approved": 1, + }, "references": {"links": ["NEP_001", "NEP_002"]}, }, { @@ -66,11 +81,16 @@ def __init__(self): @staticmethod def json(): - return {"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9", "token_type": "bearer"} + return { + "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9", + "token_type": "bearer", + } @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_open_needs_service"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_open_needs_service"}], + indirect=True, ) def test_ons_service(test_app, monkeypatch): def mock_get(*args, **kwargs): diff --git a/tests/test_parallel_execution.py b/tests/test_parallel_execution.py index 542ba1c3f..44164ffc3 100644 --- a/tests/test_parallel_execution.py +++ b/tests/test_parallel_execution.py @@ -4,7 +4,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/parallel_doc", "parallel": 4}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/parallel_doc", "parallel": 4}], + indirect=True, ) def test_doc_build_html(test_app): app = test_app @@ -16,7 +18,9 @@ def test_doc_build_html(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/parallel_doc", "parallel": 4}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/parallel_doc", "parallel": 4}], + indirect=True, ) def test_doc_parallel_build_html(test_app): app = test_app diff --git a/tests/test_report_dead_links.py b/tests/test_report_dead_links.py index fd6f88aa0..b7c69d3bf 100644 --- a/tests/test_report_dead_links.py +++ b/tests/test_report_dead_links.py @@ -5,14 +5,18 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_report_dead_links_true"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_report_dead_links_true"}], + indirect=True, ) def test_needs_dead_links_warnings(test_app): app = test_app src_dir = Path(app.srcdir) out_dir = Path(app.outdir) - output = subprocess.run(["sphinx-build", "-M", "html", src_dir, out_dir], capture_output=True) + output = subprocess.run( + ["sphinx-build", "-M", "html", src_dir, out_dir], capture_output=True + ) # check there are expected warnings stderr = output.stderr.decode("utf-8") @@ -25,14 +29,18 @@ def test_needs_dead_links_warnings(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "needs", "srcdir": "doc_test/doc_report_dead_links_true"}], indirect=True + "test_app", + [{"buildername": "needs", "srcdir": "doc_test/doc_report_dead_links_true"}], + indirect=True, ) def test_needs_dead_links_warnings_needs_builder(test_app): app = test_app src_dir = Path(app.srcdir) out_dir = Path(app.outdir) - output = subprocess.run(["sphinx-build", "-M", "needs", src_dir, out_dir], capture_output=True) + output = subprocess.run( + ["sphinx-build", "-M", "needs", src_dir, out_dir], capture_output=True + ) # check there are expected warnings stderr = output.stderr.decode("utf-8") @@ -45,14 +53,18 @@ def test_needs_dead_links_warnings_needs_builder(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_report_dead_links_false"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_report_dead_links_false"}], + indirect=True, ) def test_needs_dead_links_suppress_warnings(test_app): app = test_app src_dir = Path(app.srcdir) out_dir = Path(app.outdir) - output = subprocess.run(["sphinx-build", "-M", "html", src_dir, out_dir], capture_output=True) + output = subprocess.run( + ["sphinx-build", "-M", "html", src_dir, out_dir], capture_output=True + ) # check there are no warnings assert not output.stderr diff --git a/tests/test_role_need.py b/tests/test_role_need.py index a8119c001..7f1fc0dae 100644 --- a/tests/test_role_need.py +++ b/tests/test_role_need.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/role_need_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/role_need_doc"}], + indirect=True, +) def test_role_need(test_app): app = test_app app.build() @@ -24,5 +28,6 @@ def test_role_need(test_app): # External need ref assert ( 'EXT_TEST_01' in html + 'href="http://my_company.com/docs/v1/index.html#TEST_01">EXT_TEST_01' + in html ) diff --git a/tests/test_role_need_max_title_length.py b/tests/test_role_need_max_title_length.py index c8a9c1616..e6ab88963 100644 --- a/tests/test_role_need_max_title_length.py +++ b/tests/test_role_need_max_title_length.py @@ -6,7 +6,12 @@ @pytest.mark.parametrize( "test_app", - [{"buildername": "html", "srcdir": "doc_test/doc_role_need_max_title_length_unlimited"}], + [ + { + "buildername": "html", + "srcdir": "doc_test/doc_role_need_max_title_length_unlimited", + } + ], indirect=True, ) def test_max_title_length_unlimited(test_app): @@ -23,7 +28,9 @@ def test_max_title_length_unlimited(test_app): @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_role_need_max_title_length"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_role_need_max_title_length"}], + indirect=True, ) def test_max_title_length_10(test_app): os.environ["MAX_TITLE_LENGTH"] = "10" diff --git a/tests/test_role_need_template.py b/tests/test_role_need_template.py index 2a15a740d..8e2aa4e88 100644 --- a/tests/test_role_need_template.py +++ b/tests/test_role_need_template.py @@ -4,7 +4,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_role_need_template"}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_role_need_template"}], + indirect=True, ) def test_doc_build_html(test_app): app = test_app diff --git a/tests/test_services/test_service_basics.py b/tests/test_services/test_service_basics.py index af961353a..f0b3254f0 100644 --- a/tests/test_services/test_service_basics.py +++ b/tests/test_services/test_service_basics.py @@ -34,7 +34,10 @@ def debug(self, options): "url": "http://dummy.company.com/my/service", "user": "my_user", }, - "answer": {"status_code": 200, "body": {"item_amount": 2, "items": ["item_1", "item_2"]}}, + "answer": { + "status_code": 200, + "body": {"item_amount": 2, "items": ["item_1", "item_2"]}, + }, } return debug_data @@ -50,7 +53,11 @@ def request(self, _options): return [] -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/service_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/service_doc"}], + indirect=True, +) def test_service_creation(test_app): app = test_app app.build() diff --git a/tests/test_styles/test_style_blank.py b/tests/test_styles/test_style_blank.py index ae34cf0b3..f4934b42b 100644 --- a/tests/test_styles/test_style_blank.py +++ b/tests/test_styles/test_style_blank.py @@ -5,7 +5,11 @@ from sphinx.builders.html import StandaloneHTMLBuilder -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_style_blank"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_style_blank"}], + indirect=True, +) def test_doc_style_blank(test_app): # css_files is not cleared between test runs so css files get # progressively added. This forces it to clear before re-building diff --git a/tests/test_styles/test_style_css_js_registration.py b/tests/test_styles/test_style_css_js_registration.py index a12b0b9f6..31866c334 100644 --- a/tests/test_styles/test_style_css_js_registration.py +++ b/tests/test_styles/test_style_css_js_registration.py @@ -26,8 +26,16 @@ def test_file_registration(): sphinx_app.build() # Only check Sphinx-Needs files - css_files = [x for x in sphinx_app.builder.css_files if x.startswith("_static/sphinx-needs")] - script_files = [x for x in sphinx_app.builder.script_files if x.startswith("_static/sphinx-needs")] + css_files = [ + x + for x in sphinx_app.builder.css_files + if x.startswith("_static/sphinx-needs") + ] + script_files = [ + x + for x in sphinx_app.builder.script_files + if x.startswith("_static/sphinx-needs") + ] css_run_1 = len(css_files) script_run_1 = len(script_files) @@ -41,8 +49,16 @@ def test_file_registration(): sphinx_app.build() # Only check Sphinx-Needs files - css_files = [x for x in sphinx_app.builder.css_files if x.startswith("_static/sphinx-needs")] - script_files = [x for x in sphinx_app.builder.script_files if x.startswith("_static/sphinx-needs")] + css_files = [ + x + for x in sphinx_app.builder.css_files + if x.startswith("_static/sphinx-needs") + ] + script_files = [ + x + for x in sphinx_app.builder.script_files + if x.startswith("_static/sphinx-needs") + ] css_run_2 = len(css_files) script_run_2 = len(script_files) diff --git a/tests/test_styles/test_style_custom.py b/tests/test_styles/test_style_custom.py index b76fa309b..e2f392fd0 100644 --- a/tests/test_styles/test_style_custom.py +++ b/tests/test_styles/test_style_custom.py @@ -5,7 +5,11 @@ from sphinx.builders.html import StandaloneHTMLBuilder -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_style_custom"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_style_custom"}], + indirect=True, +) def test_doc_style_custom(test_app): # css_files is not cleared between test runs so css files get # progressively added. This forces it to clear before re-building diff --git a/tests/test_styles/test_style_modern.py b/tests/test_styles/test_style_modern.py index 2e8fa8134..6c9956216 100644 --- a/tests/test_styles/test_style_modern.py +++ b/tests/test_styles/test_style_modern.py @@ -5,7 +5,11 @@ from sphinx.builders.html import StandaloneHTMLBuilder -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_style_modern"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_style_modern"}], + indirect=True, +) def test_doc_style_modern(test_app): # css_files is not cleared between test runs so css files get # progressively added. This forces it to clear before re-building diff --git a/tests/test_styles/test_style_unknown.py b/tests/test_styles/test_style_unknown.py index 6278ce31d..c934525a0 100644 --- a/tests/test_styles/test_style_unknown.py +++ b/tests/test_styles/test_style_unknown.py @@ -5,7 +5,11 @@ from sphinx.builders.html import StandaloneHTMLBuilder -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_style_unknown"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/doc_style_unknown"}], + indirect=True, +) def test_doc_style_unknown(test_app): # css_files is not cleared between test runs so css files get # progressively added. This forces it to clear before re-building diff --git a/tests/test_test_doc.py b/tests/test_test_doc.py index 188971f07..8dbb8792d 100644 --- a/tests/test_test_doc.py +++ b/tests/test_test_doc.py @@ -3,7 +3,11 @@ import pytest -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/generic_doc"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/generic_doc"}], + indirect=True, +) def test_doc_build_html(test_app): app = test_app app.build() diff --git a/tests/test_title_from_content.py b/tests/test_title_from_content.py index 8bc99e7fd..28154d883 100644 --- a/tests/test_title_from_content.py +++ b/tests/test_title_from_content.py @@ -5,7 +5,11 @@ from tests.util import extract_needs_from_html -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/title_from_content"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/title_from_content"}], + indirect=True, +) def test_title_from_content_scenarios(test_app): app = test_app app.build() diff --git a/tests/test_title_optional.py b/tests/test_title_optional.py index b8333e960..972eb5e9f 100644 --- a/tests/test_title_optional.py +++ b/tests/test_title_optional.py @@ -21,10 +21,16 @@ def id(self): @property def title(self): title = self.need.find(".//html:span[@class='needs_title']", NS) - return title[0].text if title is not None else None # title[0] aims to the span_data element + return ( + title[0].text if title is not None else None + ) # title[0] aims to the span_data element -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/title_optional"}], indirect=True) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/title_optional"}], + indirect=True, +) def test_title_optional_scenarios(test_app): app = test_app app.build() diff --git a/tests/test_unicode.py b/tests/test_unicode.py index a43fddc64..d2148d204 100644 --- a/tests/test_unicode.py +++ b/tests/test_unicode.py @@ -4,8 +4,14 @@ import pytest -@pytest.mark.skipif(sys.platform == "win32", reason="assert fails on windows, need to fix later.") -@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/unicode_support"}], indirect=True) +@pytest.mark.skipif( + sys.platform == "win32", reason="assert fails on windows, need to fix later." +) +@pytest.mark.parametrize( + "test_app", + [{"buildername": "html", "srcdir": "doc_test/unicode_support"}], + indirect=True, +) def test_unicode_html(test_app): app = test_app app.build() diff --git a/tests/test_unsafe_filter_for_filter_func.py b/tests/test_unsafe_filter_for_filter_func.py index 006784f09..23d9381ac 100644 --- a/tests/test_unsafe_filter_for_filter_func.py +++ b/tests/test_unsafe_filter_for_filter_func.py @@ -4,7 +4,14 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/doc_needs_filter_func_allow_dirty_filter"}], indirect=True + "test_app", + [ + { + "buildername": "html", + "srcdir": "doc_test/doc_needs_filter_func_allow_dirty_filter", + } + ], + indirect=True, ) def test_doc_allow_unsafe_filter_for_filter_func(test_app): app = test_app diff --git a/tests/test_variants.py b/tests/test_variants.py index b91c5cba4..b9c3479a1 100644 --- a/tests/test_variants.py +++ b/tests/test_variants.py @@ -4,7 +4,9 @@ @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/variant_doc", "tags": ["tag_a"]}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/variant_doc", "tags": ["tag_a"]}], + indirect=True, ) def test_variant_options_html(test_app): app = test_app @@ -32,12 +34,15 @@ def test_variant_options_html(test_app): # Check if referenced link exists in html assert ( '
links outgoing: VA_003
' in html + 'internal" href="#VA_003" title="SPEC_003">VA_003
' + in html ) @pytest.mark.parametrize( - "test_app", [{"buildername": "html", "srcdir": "doc_test/variant_options", "tags": ["tag_a"]}], indirect=True + "test_app", + [{"buildername": "html", "srcdir": "doc_test/variant_options", "tags": ["tag_a"]}], + indirect=True, ) def test_empty_variant_options_html(test_app): app = test_app diff --git a/tests/util.py b/tests/util.py index 7c04aa80c..cb36b7f30 100644 --- a/tests/util.py +++ b/tests/util.py @@ -14,15 +14,21 @@ def __init__(self, need): def id(self): found_id = self.need.find(".//html:a[@class='reference internal']", NS) if found_id is None: - found_id = self.need.find(".//html:a[@class='reference internal']", {"html": ""}) + found_id = self.need.find( + ".//html:a[@class='reference internal']", {"html": ""} + ) return found_id.text @property def title(self): found_title = self.need.find(".//html:span[@class='needs_title']", NS) if found_title is None: - found_title = self.need.find(".//html:span[@class='needs_title']", {"html": ""}) - return found_title[0].text if found_title else None # title[0] aims to the span_data element + found_title = self.need.find( + ".//html:span[@class='needs_title']", {"html": ""} + ) + return ( + found_title[0].text if found_title else None + ) # title[0] aims to the span_data element def extract_needs_from_html(html):