From 5b983a46209ce04e10f389a08b604bf39eb35b11 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Mon, 21 Aug 2023 15:29:51 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=8C=20Improve=20sphinx=20warnings=20(#?= =?UTF-8?q?975)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR is intended to standardise and improve the sphinx warnings emitted by sphinx-needs: 1. To make it clear when a warning originates from sphinx-needs 2. Where possible, to add the location of the warning origin (in the source documentation) i.e. all warning logs should now look like: ``` /path/to/file.rst:: WARNING: [needs] ``` --- This is similar to my work in https://myst-parser.readthedocs.io/en/latest/configuration.html#build-warnings, it prefixes all warnings with `[needs]`, and adds the `needs` type to the warning, meaning it can be specifically suppressed (see https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-suppress_warnings). (warning subtypes could also be added in follow up PRs) I have also added the `location` argument to some warnings (where the location was obvious), although there are probably some more that could also have a location (but this can be done in later PRs), Note, IMO it would be ideal if the type was automatically shown by sphinx, but this is not currently the case: https://github.com/sphinx-doc/sphinx/issues/8845 Note also, I intend to make an upstream PR to https://github.com/sphinx-contrib/plantuml, to also improve their warnings --- docs/changelog.rst | 2 ++ sphinx_needs/api/need.py | 19 ++++++++++++++----- sphinx_needs/diagrams_common.py | 5 ++++- sphinx_needs/directives/need.py | 10 +++++++--- sphinx_needs/directives/needflow.py | 17 ++++++++++++----- sphinx_needs/directives/needgantt.py | 3 ++- sphinx_needs/directives/needimport.py | 10 +++++++--- sphinx_needs/directives/needsequence.py | 5 +++-- sphinx_needs/environment.py | 2 +- sphinx_needs/filter_common.py | 7 ++++--- sphinx_needs/functions/common.py | 4 ++-- sphinx_needs/need_constraints.py | 4 +++- sphinx_needs/needs.py | 4 ++-- sphinx_needs/needsfile.py | 4 ++-- sphinx_needs/roles/need_incoming.py | 2 +- sphinx_needs/roles/need_outgoing.py | 12 ++++++++---- sphinx_needs/roles/need_part.py | 5 +++-- sphinx_needs/roles/need_ref.py | 14 +++++++------- sphinx_needs/services/github.py | 6 ++++-- sphinx_needs/utils.py | 14 ++++++++++---- sphinx_needs/warnings.py | 9 +++++---- tests/test_broken_links.py | 2 +- tests/test_github_issues.py | 4 ++-- tests/test_report_dead_links.py | 16 ++++++++-------- 24 files changed, 114 insertions(+), 66 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 5a8b0ca72..8a1638835 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -20,6 +20,8 @@ Released: under development * Change `NeedsBuilder` format to `needs` (`#978 `_) +* Improvement: Suffix all warnings with ``[needs]``, and allow them to be suppressed (`#975 `_) + 1.3.0 ----- Released: 16.08.2023 diff --git a/sphinx_needs/api/need.py b/sphinx_needs/api/need.py index 3f0432d26..83a9b12b3 100644 --- a/sphinx_needs/api/need.py +++ b/sphinx_needs/api/need.py @@ -148,7 +148,8 @@ def run(): 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.".format(id, need_type) + "in the project's 'need_types' configuration in conf.py. [needs]".format(id, need_type), + type="needs", ) for ntype in types: @@ -216,7 +217,10 @@ def run(): new_tags = [] # Shall contain only valid tags 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.") + logger.warning( + f"Scruffy tag definition found in need {need_id}. " "Defined tag contains spaces only. [needs]", + type="needs", + ) else: new_tags.append(tags[i]) @@ -245,7 +249,9 @@ def run(): for i in range(len(constraints)): if len(constraints[i]) == 0 or constraints[i].isspace(): logger.warning( - f"Scruffy tag definition found in need {need_id}. " "Defined constraint contains spaces only." + f"Scruffy tag definition found in need {need_id}. " + "Defined constraint contains spaces only. [needs]", + type="needs", ) else: new_constraints.append(constraints[i]) @@ -506,7 +512,7 @@ def del_need(app: Sphinx, need_id: str) -> None: if need_id in env.needs_all_needs: del env.needs_all_needs[need_id] else: - logger.warning(f"Given need id {need_id} not exists!") + logger.warning(f"Given need id {need_id} not exists! [needs]", type="needs") def add_external_need( @@ -621,7 +627,10 @@ def _read_in_links(links_string: Union[str, List[str]]) -> List[str]: link_list = links_string for link in link_list: if link.isspace(): - logger.warning(f"Grubby link definition found in need {id}. " "Defined link contains spaces only.") + logger.warning( + f"Grubby link definition found in need {id}. " "Defined link contains spaces only. [needs]", + type="needs", + ) else: links.append(link.strip()) diff --git a/sphinx_needs/diagrams_common.py b/sphinx_needs/diagrams_common.py index a82d4aa67..6f4aa9f14 100644 --- a/sphinx_needs/diagrams_common.py +++ b/sphinx_needs/diagrams_common.py @@ -67,7 +67,10 @@ def collect_diagram_attributes(self) -> Dict[str, Any]: if len(link_types[i]) == 0 or link_types[i].isspace(): del link_types[i] logger.warning( - "Scruffy link_type definition found in needsequence. " "Defined link_type contains spaces only." + "Scruffy link_type definition found in needsequence. " + "Defined link_type contains spaces only. [needs]", + type="needs", + location=(env.docname, self.lineno), ) config_names = self.options.get("config") diff --git a/sphinx_needs/directives/need.py b/sphinx_needs/directives/need.py index b48bed484..1f8663576 100644 --- a/sphinx_needs/directives/need.py +++ b/sphinx_needs/directives/need.py @@ -157,7 +157,9 @@ def read_in_links(self, name: str) -> List[str]: if link.isspace(): logger.warning( f"Grubby link definition found in need '{self.trimmed_title}'. " - "Defined link contains spaces only." + "Defined link contains spaces only. [needs]", + type="needs", + location=(self.env.docname, self.lineno), ) else: links.append(link.strip()) @@ -206,8 +208,10 @@ 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( - 'Needs: need "{}" has :title_from_content: set, ' - "but a title was provided. (see file {})".format(self.arguments[0], self.docname) + 'need "{}" has :title_from_content: set, ' + "but a title was provided. (see file {}) [needs]".format(self.arguments[0], self.docname), + type="needs", + location=(self.env.docname, self.lineno), ) return self.arguments[0] elif self.title_from_content: diff --git a/sphinx_needs/directives/needflow.py b/sphinx_needs/directives/needflow.py index 5061be73a..d22765b71 100644 --- a/sphinx_needs/directives/needflow.py +++ b/sphinx_needs/directives/needflow.py @@ -64,7 +64,9 @@ def run(self) -> Sequence[nodes.Node]: targetnode = nodes.target("", "", ids=[targetid]) all_link_types = ",".join(x["option"] for x in env.config.needs_extra_links) - link_types = list(split_link_types(self.options.get("link_types", all_link_types))) + link_types = list( + split_link_types(self.options.get("link_types", all_link_types), location=(env.docname, self.lineno)) + ) config_names = self.options.get("config") configs = [] @@ -110,10 +112,14 @@ def run(self) -> Sequence[nodes.Node]: return [targetnode, Needflow("")] -def split_link_types(link_types: str) -> Iterable[str]: +def split_link_types(link_types: str, location=None) -> Iterable[str]: def is_valid(link_type: str) -> bool: if len(link_type) == 0 or link_type.isspace(): - logger.warning("Scruffy link_type definition found in needflow." "Defined link_type contains spaces only.") + logger.warning( + "Scruffy link_type definition found in needflow." "Defined link_type contains spaces only. [needs]", + type="needs", + location=location, + ) return False return True @@ -309,9 +315,10 @@ def process_needflow(app: Sphinx, doctree: nodes.document, fromdocname: str, fou for lt in option_link_types: if lt not in [link["option"].upper() for link in link_types]: logger.warning( - "Unknown link type {link_type} in needflow {flow}. Allowed values: {link_types}".format( + "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_types) - ) + ), + type="needs", ) content = [] diff --git a/sphinx_needs/directives/needgantt.py b/sphinx_needs/directives/needgantt.py index b43dc677a..082a02ef9 100644 --- a/sphinx_needs/directives/needgantt.py +++ b/sphinx_needs/directives/needgantt.py @@ -204,7 +204,8 @@ def process_needgantt(app, doctree, fromdocname, found_nodes): if not (duration and duration.isdigit()): logger.warning( "Duration not set or invalid for needgantt chart. " - "Need: {}. Duration: {}".format(need["id"], duration) + "Need: {}. Duration: {} [needs]".format(need["id"], duration), + type="needs", ) duration = 1 gantt_element = "[{}] as [{}] lasts {} days\n".format(need["title"], need["id"], duration) diff --git a/sphinx_needs/directives/needimport.py b/sphinx_needs/directives/needimport.py index 5a78825dd..ecfa40880 100644 --- a/sphinx_needs/directives/needimport.py +++ b/sphinx_needs/directives/needimport.py @@ -88,7 +88,9 @@ def run(self) -> Sequence[nodes.Node]: logger.warning( "Deprecation warning: Relative path must be relative to the current document in future, " "not to the conf.py location. Use a starting '/', like '/needs.json', to make the path " - "relative to conf.py." + "relative to conf.py. [needs]", + type="needs", + location=(self.env.docname, self.lineno), ) else: # Absolute path starts with /, based on the source directory. The / need to be striped @@ -140,9 +142,11 @@ def run(self) -> Sequence[nodes.Node]: needs_list_filtered[key] = need except Exception as e: logger.warning( - "needimport: Filter {} not valid. Error: {}. {}{}".format( + "needimport: Filter {} not valid. Error: {}. {}{} [needs]".format( filter_string, e, self.docname, self.lineno - ) + ), + type="needs", + location=(self.env.docname, self.lineno), ) needs_list = needs_list_filtered diff --git a/sphinx_needs/directives/needsequence.py b/sphinx_needs/directives/needsequence.py index deaef7aa5..a9d2f6684 100644 --- a/sphinx_needs/directives/needsequence.py +++ b/sphinx_needs/directives/needsequence.py @@ -104,9 +104,10 @@ def process_needsequence(app: Sphinx, doctree: nodes.document, fromdocname: str, if lt not in [link["option"].upper() for link in link_types]: logger.warning( "Unknown link type {link_type} in needsequence {flow}. Allowed values:" - " {link_types}".format( + " {link_types} [needs]".format( link_type=lt, flow=current_needsequence["target_id"], link_types=",".join(link_types) - ) + ), + type="needs", ) content = [] diff --git a/sphinx_needs/environment.py b/sphinx_needs/environment.py index 5570ade54..2f58cc1b6 100644 --- a/sphinx_needs/environment.py +++ b/sphinx_needs/environment.py @@ -111,7 +111,7 @@ 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") + 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) diff --git a/sphinx_needs/filter_common.py b/sphinx_needs/filter_common.py index 250bc40aa..f32db9ccd 100644 --- a/sphinx_needs/filter_common.py +++ b/sphinx_needs/filter_common.py @@ -81,7 +81,7 @@ def process_filters(app: Sphinx, all_needs, current_needlist, include_external: try: all_needs = sorted(all_needs, key=lambda node: node[sort_key] or "") except KeyError as e: - log.warning(f"Sorting parameter {sort_key} not valid: Error: {e}") + log.warning(f"Sorting parameter {sort_key} not valid: Error: {e} [needs]", type="needs") # check if include external needs checked_all_needs = [] @@ -166,7 +166,7 @@ def process_filters(app: Sphinx, all_needs, current_needlist, include_external: filter_func = measure_time(category="filter_func", source="user", func=filter_func) filter_func(**context) else: - log.warning("Something went wrong running filter") + log.warning("Something went wrong running filter [needs]", type="needs") return [] # The filter results may be dirty, as it may continue manipulated needs. @@ -268,7 +268,8 @@ def filter_needs(app: Sphinx, needs, filter_string: str = "", current_need=None) found_needs.append(filter_need) except Exception as e: if not error_reported: # Let's report a filter-problem only onces - log.warning(e) + location = (current_need["docname"], current_need["lineno"]) if current_need else None + log.warning(str(e) + " [needs]", type="needs", location=location) error_reported = True return found_needs diff --git a/sphinx_needs/functions/common.py b/sphinx_needs/functions/common.py index a256834a6..d06941007 100644 --- a/sphinx_needs/functions/common.py +++ b/sphinx_needs/functions/common.py @@ -302,7 +302,7 @@ def check_linked_values( if not filter_single_need(app, needs[link], filter_string): continue except Exception as e: - logger.warning(f"CheckLinkedValues: Filter {filter_string} not valid: Error: {e}") + logger.warning(f"CheckLinkedValues: Filter {filter_string} not valid: Error: {e} [needs]", type="needs") if not one_hit and needs[link][search_option] not in search_value: return None @@ -409,7 +409,7 @@ def calc_sum(app: Sphinx, need, needs, option, filter=None, links_only: bool = F except ValueError: pass except NeedsInvalidFilter as ex: - logger.warning(f"Given filter is not valid. Error: {ex}") + logger.warning(f"Given filter is not valid. Error: {ex} [needs]", type="needs") with contextlib.suppress(ValueError): calculated_sum += float(check_need[option]) diff --git a/sphinx_needs/need_constraints.py b/sphinx_needs/need_constraints.py index ca5f2ebe4..7894622b7 100644 --- a/sphinx_needs/need_constraints.py +++ b/sphinx_needs/need_constraints.py @@ -69,7 +69,9 @@ def process_constraints(app: Sphinx, need: Dict[str, Any]) -> None: if "warn" in actions_on_fail: logger.warning( - f"Constraint {cmd} for need {need_id} FAILED! severity: {severity}", color="red" + f"Constraint {cmd} for need {need_id} FAILED! severity: {severity} [needs]", + type="needs", + color="red", ) if "break" in actions_on_fail: diff --git a/sphinx_needs/needs.py b/sphinx_needs/needs.py index aa18f4750..f956d47a0 100644 --- a/sphinx_needs/needs.py +++ b/sphinx_needs/needs.py @@ -446,7 +446,7 @@ def load_config(app: Sphinx, *_args) -> None: existing_extra_options = NEEDS_CONFIG.get("extra_options") for option in app.config.needs_extra_options: if option in existing_extra_options: - log.warning(f'extra_option "{option}" already registered.') + log.warning(f'extra_option "{option}" already registered. [needs]', type="needs") NEEDS_CONFIG.add("extra_options", {option: directives.unchanged}, dict, True) extra_options = NEEDS_CONFIG.get("extra_options") @@ -524,7 +524,7 @@ def load_config(app: Sphinx, *_args) -> None: if name not in existing_warnings: NEEDS_CONFIG.add("warnings", {name: check}, dict, append=True) else: - log.warning(f'{name} for "warnings" is already registered.') + log.warning(f'{name} for "warnings" is already registered. [needs]', type="needs") def visitor_dummy(*_args, **_kwargs) -> None: diff --git a/sphinx_needs/needsfile.py b/sphinx_needs/needsfile.py index b209d47f6..34b9bada8 100644 --- a/sphinx_needs/needsfile.py +++ b/sphinx_needs/needsfile.py @@ -110,7 +110,7 @@ def load_json(self, file) -> 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}") + 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 @@ -125,7 +125,7 @@ def load_json(self, file) -> None: try: needs_list = json.loads(needs_file_content) except json.JSONDecodeError: - self.log.warning(f"Could not decode json file {file}") + 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_incoming.py b/sphinx_needs/roles/need_incoming.py index fc45b0b2d..a75ad3f26 100644 --- a/sphinx_needs/roles/need_incoming.py +++ b/sphinx_needs/roles/need_incoming.py @@ -74,7 +74,7 @@ def process_need_incoming(app: Sphinx, doctree: nodes.document, fromdocname: str pass else: - env.warn_node("Needs: need %s not found" % node_need_backref["reftarget"], node_need_backref) + env.warn_node("need %s not found [needs]" % node_need_backref["reftarget"], 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 79d0f32c0..a8b18e4d1 100644 --- a/sphinx_needs/roles/need_outgoing.py +++ b/sphinx_needs/roles/need_outgoing.py @@ -117,25 +117,29 @@ def process_need_outgoing( and extra_links_dict[link_type]["allow_dead_links"] ): log_level = "INFO" + kwargs = {} else: # Set an extra css class, if link type is not configured to allow dead links dead_link_para.attributes["classes"].append("forbidden") log_level = "WARNING" + kwargs = {"type": "needs"} if report_dead_links: if node_need_ref and node_need_ref.line: log.log( log_level, - f"Needs: linked need {link} not found " - f"(Line {node_need_ref.line} of file {node_need_ref.source})", + f"linked need {link} not found " + f"(Line {node_need_ref.line} of file {node_need_ref.source}) [needs]", + **kwargs, ) else: log.log( log_level, - "Needs: outgoing linked need {} not found (document: {}, " - "source need {} on line {} )".format( + "outgoing linked need {} not found (document: {}, " + "source need {} on line {} ) [needs]".format( link, ref_need["docname"], ref_need["id"], ref_need["lineno"] ), + **kwargs, ) # If we have several links, we add an empty text between them diff --git a/sphinx_needs/roles/need_part.py b/sphinx_needs/roles/need_part.py index e7185b0f5..b334d6c4c 100644 --- a/sphinx_needs/roles/need_part.py +++ b/sphinx_needs/roles/need_part.py @@ -49,9 +49,10 @@ def update_need_with_parts(env: BuildEnvironment, need, part_nodes: List[NeedPar if inline_id in need["parts"]: log.warning( - "part_need id {} in need {} is already taken. need_part may get overridden.".format( + "part_need id {} in need {} is already taken. need_part may get overridden. [needs]".format( inline_id, need["id"] - ) + ), + type="needs", ) need["parts"][inline_id] = { diff --git a/sphinx_needs/roles/need_ref.py b/sphinx_needs/roles/need_ref.py index 047bcf705..638cb13af 100644 --- a/sphinx_needs/roles/need_ref.py +++ b/sphinx_needs/roles/need_ref.py @@ -108,13 +108,13 @@ def process_need_ref(app: Sphinx, doctree: nodes.document, fromdocname: str, fou try: link_text = ref_name.format(**dict_need) except KeyError as e: - link_text = '"Needs: option placeholder %s for need %s not found (Line %i of file %s)"' % ( + link_text = '"option placeholder %s for need %s not found (Line %i of file %s)"' % ( e, node_need_ref["reftarget"], node_need_ref.line, node_need_ref.source, ) - log.warning(link_text) + log.warning(link_text + " [needs]", type="needs") else: if ref_name: # If ref_name differs from the need id, we treat the "ref_name content" as title. @@ -123,10 +123,9 @@ def process_need_ref(app: Sphinx, doctree: nodes.document, fromdocname: str, fou link_text = app.config.needs_role_need_template.format(**dict_need) except KeyError as e: link_text = ( - '"Needs: 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) + log.warning(link_text + " [needs]", type="needs") node_need_ref[0].children[0] = nodes.Text(link_text) @@ -147,8 +146,9 @@ def process_need_ref(app: Sphinx, doctree: nodes.document, fromdocname: str, fou else: log.warning( - "Needs: linked need %s not found (Line %i of file %s)" - % (node_need_ref["reftarget"], node_need_ref.line, node_need_ref.source) + "linked need %s not found (Line %i of file %s) [needs]" + % (node_need_ref["reftarget"], node_need_ref.line, node_need_ref.source), + type="needs", ) node_need_ref.replace_self(new_node_ref) diff --git a/sphinx_needs/services/github.py b/sphinx_needs/services/github.py index fc03c7514..2f065feb9 100644 --- a/sphinx_needs/services/github.py +++ b/sphinx_needs/services/github.py @@ -292,14 +292,16 @@ def _get_avatar(self, avatar_url: str) -> str: " 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.".format(self.name, avatar_url, response.status_code) + "if you use GitHub Enterprise. [needs]".format(self.name, avatar_url, response.status_code), + type="needs", ) avatar_file_path = default_avatar_file_path else: self.log.warning( "GitHub service {} could not download avatar image " "from {}.\n" - " Status code: {}".format(self.name, avatar_url, response.status_code) + " Status code: {} [needs]".format(self.name, avatar_url, response.status_code), + type="needs", ) avatar_file_path = default_avatar_file_path else: diff --git a/sphinx_needs/utils.py b/sphinx_needs/utils.py index 98b93849f..e8ac8e5bc 100644 --- a/sphinx_needs/utils.py +++ b/sphinx_needs/utils.py @@ -308,7 +308,9 @@ def check_and_get_external_filter_func(current_needlist): try: 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') + logger.warning( + f'Filter function not valid "{filter_func_ref}". Example: my_module:my_func [needs]', type="needs" + ) return [] # No needs were found because of invalid filter function result = re.search(r"^(\w+)(?:\((.*)\))*$", filter_function) @@ -319,7 +321,7 @@ def check_and_get_external_filter_func(current_needlist): 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}") + logger.warning(f"Could not import filter function: {filter_func_ref} [needs]", type="needs") return [] return filter_func, filter_args @@ -423,7 +425,8 @@ def match_string_link( except Exception as e: logger.warning( f'Problems dealing with string to link transformation for value "{data}" of ' - f'option "{need_key}". Error: {e}' + f'option "{need_key}". Error: {e} [needs]', + type="needs", ) else: return ref_item @@ -473,7 +476,10 @@ def variant_handling( no_variants_in_option = False return output.lstrip(":") except Exception as e: - logger.warning(f'There was an error in the filter statement: "{filter_string}". ' f"Error Msg: {e}") + logger.warning( + f'There was an error in the filter statement: "{filter_string}". ' f"Error Msg: {e} [needs]", + type="needs", + ) else: no_variants_in_option = True diff --git a/sphinx_needs/warnings.py b/sphinx_needs/warnings.py index 775f350ef..07e89ebc5 100644 --- a/sphinx_needs/warnings.py +++ b/sphinx_needs/warnings.py @@ -70,7 +70,7 @@ def process_warnings(app: Sphinx, exception: Optional[Exception]) -> None: if warning_filter(need, logger): result.append(need) else: - logger.warning(f"Unknown needs warnings filter {warning_filter}!") + logger.warning(f"Unknown needs warnings filter {warning_filter}! [needs]", type="needs") if len(result) == 0: logger.info(f"{warning_name}: passed") @@ -94,9 +94,10 @@ def process_warnings(app: Sphinx, exception: Optional[Exception]) -> None: if warnings_always_warn: logger.warning( - "{}: failed\n\t\tfailed needs: {} ({})\n\t\tused filter: {}".format( + "{}: failed\n\t\tfailed needs: {} ({})\n\t\tused filter: {} [needs]".format( warning_name, len(need_ids), ", ".join(need_ids), warning_text - ) + ), + type="needs", ) else: logger.info( @@ -107,4 +108,4 @@ def process_warnings(app: Sphinx, exception: Optional[Exception]) -> None: warning_raised = True if warning_raised: - logger.warning("Sphinx-Needs warnings were raised. See console / log output for details.") + logger.warning("warnings were raised. See console / log output for details. [needs]", type="needs") diff --git a/tests/test_broken_links.py b/tests/test_broken_links.py index bbb0c5d28..4b2710749 100644 --- a/tests/test_broken_links.py +++ b/tests/test_broken_links.py @@ -10,4 +10,4 @@ def test_doc_build_html(test_app): # stdout warnings warnings = warning.getvalue() - assert "Needs: linked need BROKEN_LINK not found" in warnings + assert "linked need BROKEN_LINK not found" in warnings diff --git a/tests/test_github_issues.py b/tests/test_github_issues.py index be7ae2af4..6dd514323 100644 --- a/tests/test_github_issues.py +++ b/tests/test_github_issues.py @@ -28,8 +28,8 @@ def test_doc_github_44(test_app): assert "Test 2" in html assert "Test 3" in html - assert "Needs: linked need test_3 not found" not in output - assert "Needs: outgoing linked need test_123_broken not found" in output + assert "linked need test_3 not found" not in output + assert "outgoing linked need test_123_broken not found" in output @pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_github_issue_61"}], indirect=True) diff --git a/tests/test_report_dead_links.py b/tests/test_report_dead_links.py index 6380dcee1..24a8d9008 100644 --- a/tests/test_report_dead_links.py +++ b/tests/test_report_dead_links.py @@ -20,16 +20,16 @@ def test_needs_report_dead_links_true(test_app): # Check log info msg of dead links assert ( - "Needs: outgoing linked need DEAD_LINK_ALLOWED not found (document: index, source need REQ_001 on line 7 )" + "outgoing linked need DEAD_LINK_ALLOWED not found (document: index, source need REQ_001 on line 7 ) [needs]" in output.stdout.decode("utf-8") ) # Check log warning msg of dead links assert ( - "WARNING: Needs: outgoing linked need ANOTHER_DEAD_LINK not found (document: index, " - "source need REQ_004 on line 17 )" in output.stderr.decode("utf-8") + "WARNING: outgoing linked need ANOTHER_DEAD_LINK not found (document: index, " + "source need REQ_004 on line 17 ) [needs]" in output.stderr.decode("utf-8") ) assert ( - "WARNING: Needs: outgoing linked need REQ_005 not found (document: index, source need TEST_004 on line 45 )" + "WARNING: outgoing linked need REQ_005 not found (document: index, source need TEST_004 on line 45 ) [needs]" in output.stderr.decode("utf-8") ) @@ -51,16 +51,16 @@ def test_needs_report_dead_links_false(test_app): # Check log info msg of dead links deactivated assert ( - "Needs: outgoing linked need DEAD_LINK_ALLOWED not found (document: index, source need REQ_001 on line 7 )" + "outgoing linked need DEAD_LINK_ALLOWED not found (document: index, source need REQ_001 on line 7 ) [needs]" not in output.stdout.decode("utf-8") ) # Check log warning msg of dead links deactivated assert ( - "WARNING: Needs: outgoing linked need ANOTHER_DEAD_LINK not found (document: index, " - "source need REQ_004 on line 17 )" not in output.stderr.decode("utf-8") + "WARNING: outgoing linked need ANOTHER_DEAD_LINK not found (document: index, " + "source need REQ_004 on line 17 ) [needs]" not in output.stderr.decode("utf-8") ) assert ( - "WARNING: Needs: outgoing linked need REQ_005 not found (document: index, source need TEST_004 on line 45 )" + "WARNING: outgoing linked need REQ_005 not found (document: index, source need TEST_004 on line 45 ) [needs]" not in output.stderr.decode("utf-8") ) assert not output.stderr