Skip to content

Commit

Permalink
👌 Allow needextend to use dynamic functions (#1052)
Browse files Browse the repository at this point in the history
It is of note that a key change here is that we alter the needs data post-processing order,
to extend the needs, before processing dynamic values, links and constraints.
  • Loading branch information
chrisjsewell committed Oct 27, 2023
1 parent 38c2870 commit d8b0a28
Show file tree
Hide file tree
Showing 7 changed files with 383 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ jobs:
name: "py${{ matrix.python-version }} sp${{ matrix.sphinx-version }} do${{ matrix.docutils-version }} ${{ matrix.os }}"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true # Set on "false" to get the results of ALL builds
fail-fast: false # Set on "false" to get the results of ALL builds
matrix:
os: ["ubuntu-latest"]
# 3.9.8 seems to be broken with type_ast
Expand Down
2 changes: 1 addition & 1 deletion sphinx_needs/directives/need.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,12 +383,12 @@ def process_need_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str) -
return

if not needs_data.needs_is_post_processed:
extend_needs_data(needs, needs_data.get_or_create_extends(), needs_config)
resolve_dynamic_values(needs, app)
resolve_variants_options(needs, needs_config, app.builder.tags.tags)
check_links(needs, needs_config)
create_back_links(needs, needs_config)
process_constraints(needs, needs_config)
extend_needs_data(needs, needs_data.get_or_create_extends(), needs_config)
needs_data.needs_is_post_processed = True

for extend_node in doctree.findall(Needextend):
Expand Down
76 changes: 36 additions & 40 deletions sphinx_needs/directives/needextend.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,7 @@ def extend_needs_data(
) -> None:
"""Use data gathered from needextend directives to modify fields of existing needs."""

list_values = (
["tags", "links"]
+ [x["option"] for x in needs_config.extra_links]
+ [f"{x['option']}_back" for x in needs_config.extra_links]
) # back-links (incoming)
list_values = ["tags", "links"] + [x["option"] for x in needs_config.extra_links]
link_names = [x["option"] for x in needs_config.extra_links]

for current_needextend in extends.values():
Expand Down Expand Up @@ -114,23 +110,26 @@ def extend_needs_data(
if option.startswith("+"):
option_name = option[1:]
if option_name in link_names:
# If we add links, then add all corresponding back links
for ref_need in [i.strip() for i in re.split(";|,", value)]:
if ref_need not in all_needs:
logger.warning(
f"Provided link id {ref_need} for needextend does not exist. [needs]",
type="needs",
location=(current_needextend["docname"], current_needextend["lineno"]),
)
continue
if ref_need not in need[option_name]:
need[option_name].append(ref_need)
if found_need["id"] not in all_needs[ref_need][f"{option_name}_back"]:
all_needs[ref_need][f"{option_name}_back"] += [found_need["id"]]
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)]:
if ref_need not in all_needs:
logger.warning(
f"Provided link id {ref_need} for needextend does not exist. [needs]",
type="needs",
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:
for item in [i.strip() for i in re.split(";|,", value)]:
if item not in need[option_name]:
need[option_name].append(item)
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)]:
if item not in need[option_name]:
need[option_name].append(item)
else:
if need[option_name]:
# If content is already stored, we need to add some whitespace
Expand All @@ -140,34 +139,31 @@ def extend_needs_data(
elif option.startswith("-"):
option_name = option[1:]
if option_name in link_names:
# If we remove links, then remove all corresponding back links
for ref_need in (i for i in need[option_name] if i in all_needs):
all_needs[ref_need][f"{option_name}_back"].remove(found_need["id"])
need[option_name] = []
if option_name in list_values:
need[option_name] = []
else:
need[option_name] = ""
else:
if option in link_names:
# If we change links, then modify all corresponding back links
for ref_need in (i for i in need[option] if i in all_needs):
all_needs[ref_need][f"{option}_back"].remove(found_need["id"])
need[option] = []
for ref_need in [i.strip() for i in re.split(";|,", value)]:
if ref_need not in all_needs:
logger.warning(
f"Provided link id {ref_need} for needextend does not exist. [needs]",
type="needs",
location=(current_needextend["docname"], current_needextend["lineno"]),
)
continue
need[option].append(ref_need)
for ref_need in need[option]:
if found_need["id"] not in all_needs[ref_need][f"{option}_back"]:
all_needs[ref_need][f"{option}_back"] += [found_need["id"]]
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)]:
if ref_need not in all_needs:
logger.warning(
f"Provided link id {ref_need} for needextend does not exist. [needs]",
type="needs",
location=(current_needextend["docname"], current_needextend["lineno"]),
)
continue
need[option].append(ref_need)
elif option in list_values:
need[option] = [i.strip() for i in re.split(";|,", value)]
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)]
else:
need[option] = value

Expand Down
Loading

0 comments on commit d8b0a28

Please sign in to comment.