Skip to content

Commit

Permalink
🔧 Add strict typing for sphinx_needs.directives.need
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisjsewell committed Aug 28, 2023
1 parent 8994677 commit ab5ea94
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 24 deletions.
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ ignore_missing_imports = true
[[tool.mypy.overrides]]
module = [
'sphinx_needs.api.need',
'sphinx_needs.directives.need',
'sphinx_needs.directives.needuml',
'sphinx_needs.functions.functions',
'sphinx_needs.layout',
Expand Down
49 changes: 26 additions & 23 deletions sphinx_needs/directives/need.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def run(self) -> Sequence[nodes.Node]:
**need_extra_options,
)
add_doc(env, self.docname)
return need_nodes
return need_nodes # type: ignore[no-any-return]

def read_in_links(self, name: str) -> List[str]:
# Get links
Expand Down Expand Up @@ -178,7 +178,7 @@ def make_hashed_id(self, type_prefix: str, id_length: int) -> str:
)

@property
def title_from_content(self):
def title_from_content(self) -> bool:
return "title_from_content" in self.options or self.needs_config.title_from_content

@property
Expand Down Expand Up @@ -215,7 +215,7 @@ def _get_full_title(self) -> str:
type="needs",
location=(self.env.docname, self.lineno),
)
return self.arguments[0]
return self.arguments[0] # type: ignore[no-any-return]
elif self.title_from_content:
first_sentence = re.split(r"[.\n]", "\n".join(self.content))[0]
if not first_sentence:
Expand All @@ -229,7 +229,9 @@ def _get_full_title(self) -> str:
return ""


def get_sections_and_signature_and_needs(need_node) -> Tuple[List[str], Optional[nodes.Text], List[str]]:
def get_sections_and_signature_and_needs(
need_node: Optional[nodes.Node],
) -> Tuple[List[str], Optional[nodes.Text], List[str]]:
"""Gets the hierarchy of the section nodes as a list starting at the
section of the current need and then its parent sections"""
sections = []
Expand All @@ -238,7 +240,7 @@ def get_sections_and_signature_and_needs(need_node) -> Tuple[List[str], Optional
current_node = need_node
while current_node:
if isinstance(current_node, nodes.section):
title = typing.cast(str, current_node.children[0].astext()) # type: ignore[no-untyped-call]
title = typing.cast(str, current_node.children[0].astext())
# If using auto-section numbering, then Sphinx inserts
# multiple non-breaking space unicode characters into the title
# we'll replace those with a simple space to make them easier to
Expand Down Expand Up @@ -328,13 +330,13 @@ def add_sections(app: Sphinx, doctree: nodes.document) -> None:
need_info["parent_need"] = parent_needs[0]


def previous_sibling(node):
def previous_sibling(node: nodes.Node) -> Optional[nodes.Node]:
"""Return preceding sibling node or ``None``."""
try:
i = node.parent.index(node)
i = node.parent.index(node) # type: ignore
except AttributeError:
return None
return node.parent[i - 1] if i > 0 else None
return node.parent[i - 1] if i > 0 else None # type: ignore


@profile("NEED_PROCESS")
Expand All @@ -352,7 +354,8 @@ def process_need_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str) -
needs_config = NeedsSphinxConfig(app.config)
if not needs_config.include_needs:
for node in doctree.findall(Need):
node.parent.remove(node)
if node.parent is not None:
node.parent.remove(node) # type: ignore
return

builder = unwrap(app.builder)
Expand Down Expand Up @@ -400,7 +403,7 @@ def process_need_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str) -


@profile("NEED_PRINT")
def print_need_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str, found_needs_nodes: list) -> None:
def print_need_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str, found_needs_nodes: List[Need]) -> None:
"""
Finally creates the need-node in the docutils node-tree.
Expand Down Expand Up @@ -445,7 +448,7 @@ def check_links(env: BuildEnvironment) -> None:
for link_type in extra_links:
dead_links_allowed = link_type.get("allow_dead_links", False)
need_link_value = (
[need[link_type["option"]]] if isinstance(need[link_type["option"]], str) else need[link_type["option"]]
[need[link_type["option"]]] if isinstance(need[link_type["option"]], str) else need[link_type["option"]] # type: ignore
)
for link in need_link_value:
if "." in link:
Expand All @@ -465,7 +468,7 @@ def check_links(env: BuildEnvironment) -> None:
workflow["links_checked"] = True


def create_back_links(env: BuildEnvironment, option) -> None:
def create_back_links(env: BuildEnvironment, option: str) -> None:
"""
Create back-links in all found needs.
But do this only once, as all needs are already collected and this sorting is for all
Expand All @@ -476,12 +479,12 @@ def create_back_links(env: BuildEnvironment, option) -> None:
data = SphinxNeedsData(env)
workflow = data.get_or_create_workflow()
option_back = f"{option}_back"
if workflow[f"backlink_creation_{option}"]:
if workflow[f"backlink_creation_{option}"]: # type: ignore[literal-required]
return

needs = data.get_or_create_needs()
for key, need in needs.items():
need_link_value = [need[option]] if isinstance(need[option], str) else need[option]
need_link_value = [need[option]] if isinstance(need[option], str) else need[option] # type: ignore[literal-required]
for link in need_link_value:
link_main = link.split(".")[0]
try:
Expand All @@ -490,16 +493,16 @@ def create_back_links(env: BuildEnvironment, option) -> None:
link_part = None

if link_main in needs:
if key not in needs[link_main][option_back]:
needs[link_main][option_back].append(key)
if key not in needs[link_main][option_back]: # type: ignore[literal-required]
needs[link_main][option_back].append(key) # type: ignore[literal-required]

# Handling of links to need_parts inside a need
if link_part and link_part in needs[link_main]["parts"]:
if option_back not in needs[link_main]["parts"][link_part].keys():
needs[link_main]["parts"][link_part][option_back] = []
needs[link_main]["parts"][link_part][option_back].append(key)
needs[link_main]["parts"][link_part][option_back] = [] # type: ignore[literal-required]
needs[link_main]["parts"][link_part][option_back].append(key) # type: ignore[literal-required]

workflow[f"backlink_creation_{option}"] = True
workflow[f"backlink_creation_{option}"] = True # type: ignore[literal-required]


def _fix_list_dyn_func(list: List[str]) -> List[str]:
Expand Down Expand Up @@ -547,21 +550,21 @@ def _fix_list_dyn_func(list: List[str]) -> List[str]:
# Need-Node.


def html_visit(self, node) -> None:
def html_visit(self: Any, node: nodes.Node) -> None:
"""
Visitor method for Need-node of builder 'html'.
Does only wrap the Need-content into an extra <div> with class=need
"""
self.body.append(self.starttag(node, "div", "", CLASS="need"))


def html_depart(self, node) -> None:
def html_depart(self: Any, node: nodes.Node) -> None:
self.body.append("</div>")


def latex_visit(self, node) -> None:
def latex_visit(self: Any, node: nodes.Node) -> None:
pass


def latex_depart(self, node) -> None:
def latex_depart(self: Any, node: nodes.Node) -> None:
pass

0 comments on commit ab5ea94

Please sign in to comment.