Skip to content

Recognize trace operations in docstrings#1059

Open
gaoflow wants to merge 3 commits into
marshmallow-code:devfrom
gaoflow:add-trace-to-path-keys
Open

Recognize trace operations in docstrings#1059
gaoflow wants to merge 3 commits into
marshmallow-code:devfrom
gaoflow:add-trace-to-path-keys

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 23, 2026

Copy link
Copy Markdown

Summary

load_operations_from_docstring filters the keys of a view docstring against PATH_KEYS, which omitted "trace":

PATH_KEYS = {"get", "put", "post", "delete", "options", "head", "patch"}

So a trace: operation defined in a docstring is silently dropped:

>>> from apispec.yaml_utils import load_operations_from_docstring
>>> doc = "Example.\n---\nget:\n    responses: {200: {description: ok}}\ntrace:\n    responses: {200: {description: ok}}\n"
>>> sorted(load_operations_from_docstring(doc))
['get']        # 'trace' is missing

This is inconsistent with the rest of apispec, which treats TRACE as a first-class OpenAPI v3 operation:

  • core.py: VALID_METHODS_OPENAPI_V3 = VALID_METHODS_OPENAPI_V2 + ["trace"]
  • core.py: resolve_refs_in_path iterates all eight methods, including trace

Only PATH_KEYS in yaml_utils.py was missed. The same docstring's get: operation is kept, confirming this is an oversight rather than intent.

Fix

Add "trace" to PATH_KEYS, mirroring VALID_METHODS_OPENAPI_V3.

Verification

  • Reproduced on dev (41784ce): trace is dropped from load_operations_from_docstring (and end-to-end, absent from spec.to_dict()["paths"]); with the fix it is preserved.
  • Added test_load_operations_from_docstring_trace; it fails before the fix and passes after.
  • Full suite: 619 passed, 6 skipped (baseline 618 + the new test), no regressions. ruff check and ruff format --check clean.

This pull request was prepared with the assistance of AI, under my direction and review.

gaoflow added 2 commits June 23, 2026 09:19
load_operations_from_docstring filters docstring keys against PATH_KEYS,
which omitted "trace". A trace: operation defined in a view docstring was
silently dropped, even though OpenAPI v3 (VALID_METHODS_OPENAPI_V3) and
the rest of apispec (e.g. resolve_refs_in_path) treat trace as a
first-class operation. Add "trace" to PATH_KEYS.
@lafrech

lafrech commented Jun 23, 2026

Copy link
Copy Markdown
Member

Thanks for contributing.

Wondering if we should make this v3 only like VALID_METHODS. It might be difficult to implement and my stance in general is to be lax with this and assume users know what they are doing.

The non-reg test could be broadened to test all methods. Currently, tests pass if we remove options from the list. Maybe using a parametrized test.

@gaoflow

gaoflow commented Jun 26, 2026

Copy link
Copy Markdown
Author

Thanks for the guidance. I pushed 0909e82 to address it.

What changed:

  • yaml_utils.PATH_KEYS now derives from VALID_METHODS_OPENAPI_V3, so the docstring parser uses the same v3 method superset instead of carrying a separate hand-maintained set.
  • The docstring regression is now parametrized over every path method (get, put, post, delete, options, head, patch, trace) so removing any one method from the parser list will fail the test.
  • Added a core test showing the version-specific behavior still lives in APISpec.path: trace is accepted for OpenAPI 3 and rejected for OpenAPI 2 via the existing VALID_METHODS validation.

Verification:

  • uv run --extra marshmallow --extra yaml pytest tests/test_yaml_utils.py::test_load_operations_from_docstring_path_methods tests/test_core.py::TestPath::test_trace_path_method_is_openapi3_only -q
  • uv run --extra marshmallow --extra yaml pytest tests/test_yaml_utils.py tests/test_core.py::TestPath -q
  • uv run --with ruff==0.15.15 ruff format --check src/apispec/yaml_utils.py tests/test_yaml_utils.py tests/test_core.py
  • uv run --with ruff==0.15.15 ruff check src/apispec/yaml_utils.py tests/test_yaml_utils.py tests/test_core.py
  • git diff --check

@lafrech lafrech left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

Comment thread src/apispec/yaml_utils.py


PATH_KEYS = {"get", "put", "post", "delete", "options", "head", "patch"}
PATH_KEYS = set(VALID_METHODS_OPENAPI_V3)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I understand the benefit of avoiding redundancy, I believe this set just "happens" to be equal to the v3 list.

To be precise, it should be the union of the valid methods for all OpenAPI versions. Frankly, we can keep it as it was defined before. It is not really duplication. And it doesn't change every other day.

Comment thread tests/test_core.py
spec.path(path="/path", operations={method: {}})
assert list(spec.to_dict()["paths"]["/path"]) == methods

def test_trace_path_method_is_openapi3_only(self):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't even test that.

Also, my comment about PATH_KEYS not being adapted to OpenAPI was kinda pointless: we don't really mind since VALID_METHODS is where the validation happens.

Comment thread tests/test_yaml_utils.py
assert yaml_utils.load_operations_from_docstring(docstring) == {}


@pytest.mark.parametrize(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants