Skip to content

[Fixes #14651] Management command for metadata validation - #14680

Open
etj wants to merge 1 commit into
masterfrom
14651_main_metadata_validation
Open

etj wants to merge 1 commit into
masterfrom
14651_main_metadata_validation

Conversation

@etj

@etj etj commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

For details see the related PR on 5.1.x: #14679

Checklist

For all pull requests:

  • Confirm you have read the contribution guidelines
  • You have sent a Contribution Licence Agreement (CLA) as necessary (not required for small changes, e.g., fixing typos in the documentation)
  • Make sure the first PR targets the master branch, eventual backports will be managed later. This can be ignored if the PR is fixing an issue that only happens in a specific branch, but not in newer ones.

The following are required only for core and extension modules (they are welcomed, but not required, for contrib modules):

  • There is a ticket in https://github.com/GeoNode/geonode/issues describing the issue/improvement/feature (a notable exemption is, changes not visible to end-users)
  • The issue connected to the PR must have Labels and Milestone assigned
  • PR for bug fixes and small new features are presented as a single commit
  • PR title must be in the form "[Fixes #<issue_number>] Title of the PR"
  • New unit tests have been added covering the changes, unless there is an explanation on why the tests are not necessary/implemented

Submitting the PR does not require you to check all items, but by the time it gets merged, they should be either satisfied or inapplicable.

@etj
etj requested a review from mattiagiupponi October 1, 2026 16:26
@etj etj self-assigned this Oct 1, 2026
Copilot AI balanced review requested due to automatic review settings October 1, 2026 16:26
@cla-bot cla-bot Bot added the cla-signed CLA Bot: community license agreement signed label Oct 1, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Malformed schemas can still crash validation, and resource selection bypasses subtype-specific metadata behavior.

Review effort: Balanced
Findings: 3 Medium severity · 1 Low severity

Open (4)
What changed in this PR

Adds metadata schema validation tooling and fixes schema-generation defects found during validation.

Changes:

  • Adds filtered JSON/CSV metadata validation with documented exit codes.
  • Handles nullable oneOf fields and localized thesaurus fallbacks.
  • Enforces mandatory thesauri and adds command/handler tests.
File Description
geonode/​metadata/​management/​__init__.py Defines the management package.
geonode/​metadata/​management/​commands/​__init__.py Defines the commands package.
geonode/​metadata/​management/​commands/​validate_metadata.py Implements metadata validation and reporting.
geonode/​metadata/​schemas/​base.json Makes optional metadata fields nullable.
geonode/​metadata/​handlers/​abstract.py Adds shared nullable oneOf handling.
geonode/​metadata/​handlers/​base.py Applies null options to enumerated fields.
geonode/​metadata/​handlers/​sparse.py Adds label fallback and nullable choices.
geonode/​metadata/​handlers/​thesaurus.py Enforces mandatory thesaurus selections.
geonode/​metadata/​tests/​test_handlers.py Tests required thesaurus schema behavior.
geonode/​metadata/​tests/​test_validate_metadata.py Tests command selection, reports, and exits.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +203 to +204
self.schema = schema
self.required_fields = set(schema.get("required", []))
return json.loads(json.dumps(data, cls=JSONEncoder))

def select_resources(self, ids, resource_types):
queryset = ResourceBase.objects.all()
# GeoNode injects this key in the instance for testing purposes only (resources titled "*error*")
instance.pop("extraErrors", None)

errors = self.drop_redundant(validator.iter_errors(instance))
Comment on lines +199 to +203
if oneof is None or not MetadataHandler._is_nullable(subschema): # an empty one is to be filled in
return

if not any("const" in option and option["const"] is None for option in oneof):
oneof.insert(0, {"const": None, "title": "-"}) # not "": the client turns it into None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed CLA Bot: community license agreement signed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants