diff --git a/docs/dynamic_functions.rst b/docs/dynamic_functions.rst index 4d2c280b4..a621c9468 100644 --- a/docs/dynamic_functions.rst +++ b/docs/dynamic_functions.rst @@ -24,6 +24,16 @@ To refer to a dynamic function, you can use the following syntax: This need has id :ndf:`copy("id")` and status :ndf:`copy("status")`. +Dynamic functions can be used for the following directive options: + +- ``status`` +- ``tags`` +- ``style`` +- ``constraints`` +- :ref:`needs_extra_options` +- :ref:`needs_extra_links` +- :ref:`needs_global_options` + .. deprecated:: 3.1.0 The :ref:`ndf` role replaces the use of the ``[[...]]`` syntax in need content. diff --git a/sphinx_needs/data.py b/sphinx_needs/data.py index 44df692a3..857bb6094 100644 --- a/sphinx_needs/data.py +++ b/sphinx_needs/data.py @@ -64,6 +64,8 @@ class CoreFieldParameters(TypedDict): """Whether field can be modified by needextend (False if not present).""" allow_df: NotRequired[bool] """Whether dynamic functions are allowed for this field (False if not present).""" + deprecate_df: NotRequired[bool] + """Whether dynamic functions are deprecated for this field (False if not present).""" show_in_layout: NotRequired[bool] """Whether to show the field in the rendered layout of the need by default (False if not present).""" exclude_external: NotRequired[bool] @@ -170,14 +172,14 @@ class CoreFieldParameters(TypedDict): "type": { "description": "Type of the need.", "schema": {"type": "string", "default": ""}, - "allow_df": True, + "deprecate_df": True, }, "type_name": { "description": "Name of the type.", "schema": {"type": "string", "default": ""}, "exclude_external": True, "exclude_import": True, - "allow_df": True, + "deprecate_df": True, }, "type_prefix": { "description": "Prefix of the type.", @@ -185,7 +187,7 @@ class CoreFieldParameters(TypedDict): "exclude_json": True, "exclude_external": True, "exclude_import": True, - "allow_df": True, + "deprecate_df": True, }, "type_color": { "description": "Hexadecimal color code of the type.", @@ -193,7 +195,7 @@ class CoreFieldParameters(TypedDict): "exclude_json": True, "exclude_external": True, "exclude_import": True, - "allow_df": True, + "deprecate_df": True, }, "type_style": { "description": "Style of the type.", @@ -201,7 +203,7 @@ class CoreFieldParameters(TypedDict): "exclude_json": True, "exclude_external": True, "exclude_import": True, - "allow_df": True, + "deprecate_df": True, }, "is_modified": { "description": "Whether the need was modified by needextend.", diff --git a/sphinx_needs/functions/functions.py b/sphinx_needs/functions/functions.py index 892cc6a6e..a81394c36 100644 --- a/sphinx_needs/functions/functions.py +++ b/sphinx_needs/functions/functions.py @@ -237,11 +237,18 @@ def resolve_dynamic_values(needs: NeedsMutable, app: Sphinx) -> None: config = NeedsSphinxConfig(app.config) allowed_fields: set[str] = { - *(k for k, v in NeedsCoreFields.items() if v.get("allow_df", False)), + *( + k + for k, v in NeedsCoreFields.items() + if v.get("allow_df", False) or v.get("deprecate_df", False) + ), *config.extra_options, *(link["option"] for link in config.extra_links), *config.global_options, } + deprecated_fields: set[str] = { + *(k for k, v in NeedsCoreFields.items() if v.get("deprecate_df", False)), + } for need in needs.values(): for need_option in need: @@ -267,6 +274,16 @@ def resolve_dynamic_values(needs: NeedsMutable, app: Sphinx) -> None: if func_call is None: continue + if need_option in deprecated_fields: + log_warning( + logger, + f"Usage of dynamic functions is deprecated in field {need_option!r}, found in need {need['id']!r}", + "deprecated", + location=(need["docname"], need["lineno"]) + if need.get("docname") + else None, + ) + # Replace original function string with return value of function call if func_return is None: need[need_option] = need[need_option].replace(