Closes: #665 - Support YAML for the portable schema export/preview/apply feature - #668
Closes: #665 - Support YAML for the portable schema export/preview/apply feature#668bctiemann wants to merge 3 commits into
Conversation
Adds YAML as an accepted and documented-preferred interchange format for
Custom Object Type schema documents, alongside JSON.
- Add PyYAML as an explicit dependency (previously only an incidental
transitive one via NetBox core).
- Add YAMLParser/YAMLRenderer (netbox_custom_objects/api/{parsers,renderers}.py),
built directly on PyYAML rather than pulling in djangorestframework-yaml.
- SchemaPreviewView and SchemaApplyView now accept either
Content-Type: application/yaml or application/json, and render YAML when
Accept: application/yaml is sent. A request with no Accept header still
gets JSON, so existing callers are unaffected.
- export_cot()/export_cots() are unchanged -- they already returned a plain
dict and left serialization to the caller; only the documented examples
and the two API endpoints change.
- Update docs/portable-schema.md examples to YAML, and clarify that
cot_schema_v1.json is a format-agnostic JSON Schema validator (it
validates the parsed document, not a specific wire encoding).
Closes: #665
…oints
- SchemaApplyView.post() called request.data.get(...) before checking
request.data was a dict, so a non-dict top-level body (e.g. a YAML/JSON
list) crashed with an unhandled AttributeError (500) instead of the
documented 400. Now validated up front.
- YAMLParser silently turned an empty body into {}, while JSONParser (used
on the same endpoints) raises ParseError (400) for an empty body. YAMLParser
now raises ParseError for an empty or null document too, so both formats
fail the same way for the same input.
- yaml.safe_load uses PyYAML's default YAML 1.1 boolean resolver, which
coerces unquoted no/yes/on/off (any case) to booleans -- the "Norway
problem" -- so a schema field named/valued "no" would silently become
False. YAMLParser now uses a _StrictBoolLoader that only resolves
true/false as booleans.
Added tests for all three in test_yaml_codec.py and test_schema_api.py.
|
@claude /review and limit response to actionable issues. |
|
Claude finished @bctiemann's task in 3m 13s —— View job PR Review: Support YAML for the portable schema export/preview/apply feature
The implementation is clean and well-structured. Three actionable issues: 1.
|
- YAMLRenderer.render() now returns bytes (encoded with self.charset) instead of str, matching DRF's renderer convention (JSONRenderer does the same). DRF's Response.render() happened to paper over the str case, but middleware inspecting the raw render output before encoding would not have. - YAMLParser's ParseError for a None-parsed document no longer claims the body is "empty" -- yaml.load() can't distinguish an empty body from an explicit `null` document, and the old message was misleading for the latter. Message now says the body must be a mapping, not null or empty. - SchemaPreviewView.post() now guards against a non-dict top-level body the same way SchemaApplyView already did, so both endpoints return the same non_field_errors shape for a non-dict body instead of preview's YAML-list/scalar case falling through to jsonschema's schema_errors format. Updated tests accordingly (renderer output is bytes now; added non-dict-body coverage for SchemaPreviewView). Full suite verified in a clean venv: 1227 tests, 0 failures/errors, 8 skipped.
|
Addressed all three:
|
Closes: #665
Adds YAML support for the portable schema export/preview/apply endpoints (
SchemaPreviewView,SchemaApplyView), per #665. JSON remains fully supported and is still the default when noAccept/Content-Typeheader is given, so this is backward compatible.api/parsers.py:YAMLParser(BaseParser),media_type = 'application/yaml', parses withyaml.safe_load.api/renderers.py:YAMLRenderer(BaseRenderer),media_type = 'application/yaml',format = 'yaml', renders withyaml.safe_dump(data, sort_keys=False, default_flow_style=False).api/views.py:_SCHEMA_PARSER_CLASSES = [YAMLParser, JSONParser]and_SCHEMA_RENDERER_CLASSES = [JSONRenderer, YAMLRenderer, FormlessBrowsableAPIRenderer](JSON first so a request with noAcceptheader still gets JSON).pyproject.toml: addsPyYAMLas a dependency.docs/portable-schema.md: documents both formats.tests/schema/test_yaml_codec.py(parser/renderer round-trip), plus new cases intests/schema/test_schema_api.pycovering content-negotiated preview/apply requests.Rebased onto the now-merged
feature(post #666/#667), which brought in the Django 6.1from_db()fix. Full suite verified in a clean venv (no straynetbox_branchingpackage on the path): 1218 tests, 0 failures/errors, 8 skipped.