Skip to content

Commit

Permalink
Merge pull request #309 from 4dn-dcic/drr_schema_fields
Browse files Browse the repository at this point in the history
More schema parsing
  • Loading branch information
drio18 authored Jun 12, 2024
2 parents 36d98fc + 34e8279 commit 538acd0
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 1 deletion.
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ dcicutils
Change Log
----------

8.11.0
======

* Add more schema parsing functions to `schema_utils`, including for new properties for
generating submission templates


8.10.0
======

Expand Down
50 changes: 50 additions & 0 deletions dcicutils/schema_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
from typing import Any, Dict, List, Optional, Tuple

from dcicutils.misc_utils import to_camel_case


Expand All @@ -8,6 +9,7 @@ class JsonSchemaConstants:
ARRAY = "array"
BOOLEAN = "boolean"
DEFAULT = "default"
DEPENDENT_REQUIRED = "dependentRequired"
ENUM = "enum"
FORMAT = "format"
INTEGER = "integer"
Expand All @@ -29,6 +31,10 @@ class EncodedSchemaConstants:
LINK_TO = "linkTo"
MERGE_REF = "$merge"
MIXIN_PROPERTIES = "mixinProperties"
SUBMISSION_COMMENT = "submissionComment"
SUBMISSION_EXAMPLES = "submissionExamples"
SUBMITTER_REQUIRED = "submitterRequired"
SUGGESTED_ENUM = "suggested_enum"
UNIQUE_KEY = "uniqueKey"


Expand Down Expand Up @@ -203,6 +209,50 @@ def get_description(schema: Dict[str, Any]) -> str:
return schema.get(SchemaConstants.DESCRIPTION, "")


def is_submitter_required(schema: Dict[str, Any]) -> bool:
"""Return True if the schema is marked as required for submitters.
Specifically, required for external (i.e. non-admin) submitters.
This is typically validated within the context of a oneOf, anyOf,
or allOf schema on an item type which is used within the team and
by external submitters, and is tricky to pick up on automatically.
"""
return schema.get(SchemaConstants.SUBMITTER_REQUIRED, False)


def get_submission_comment(schema: Dict[str, Any]) -> str:
"""Return the submission comment for a property.
Custom property that can be manually added to a schema to provide
additional context for submitters.
"""
return schema.get(SchemaConstants.SUBMISSION_COMMENT, "")


def get_submission_examples(schema: Dict[str, Any]) -> List[str]:
"""Return the submission example for a property.
Custom property that can be manually added to a schema to provide
an example for submitters.
"""
return schema.get(SchemaConstants.SUBMISSION_EXAMPLES, [])


def get_suggested_enum(schema: Dict[str, Any]) -> List[str]:
"""Return the suggested enum for a property.
Custom property that can be manually added to a schema to provide
a suggested list of values for submitters.
"""
return schema.get(SchemaConstants.SUGGESTED_ENUM, [])


def get_dependent_required(schema: Dict[str, Any]) -> Dict[str, List[str]]:
"""Return the dependent required properties of a schema."""
return schema.get(SchemaConstants.DEPENDENT_REQUIRED, {})


class Schema:

def __init__(self, schema: dict, type: Optional[str] = None) -> None:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "dcicutils"
version = "8.10.0"
version = "8.11.0"
description = "Utility package for interacting with the 4DN Data Portal and other 4DN resources"
authors = ["4DN-DCIC Team <[email protected]>"]
license = "MIT"
Expand Down
69 changes: 69 additions & 0 deletions test/test_schema_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,36 @@
},
"fun": {"type": "array", "items": {"type": "string"}},
}
DEPENDENT_REQUIRED = {
"bar": ["baz"],
"foo": ["fu"],
}
SCHEMA = {
"required": REQUIRED,
"anyOf": ANY_OF,
"oneOf": ONE_OF,
"identifyingProperties": IDENTIFYING_PROPERTIES,
"mixinProperties": MIXIN_PROPERTIES,
"properties": PROPERTIES,
"dependentRequired": DEPENDENT_REQUIRED,
}
FORMAT = "email"
PATTERN = "some_regex"
ENUM = ["foo", "bar"]
DESCRIPTION = "foo"
COMMENT = "bar"
EXAMPLE = ENUM
STRING_SCHEMA = {
"type": "string",
"format": FORMAT,
"pattern": PATTERN,
"linkTo": "foo",
"enum": ENUM,
"description": DESCRIPTION,
"submitterRequired": True,
"submissionComment": COMMENT,
"submissionExamples": EXAMPLE,
"suggested_enum": ENUM,
}
ARRAY_SCHEMA = {"type": "array", "items": [STRING_SCHEMA]}
OBJECT_SCHEMA = {"type": "object", "properties": {"foo": STRING_SCHEMA}}
Expand Down Expand Up @@ -363,3 +374,61 @@ def test_get_enum(schema: Dict[str, Any], expected: List[str]) -> None:
)
def test_get_description(schema: Dict[str, Any], expected: str) -> None:
assert schema_utils.get_description(schema) == expected


@pytest.mark.parametrize(
"schema,expected",
[
({}, False),
(NUMBER_SCHEMA, False),
(STRING_SCHEMA, True),
],
)
def test_is_submitter_required(schema: Dict[str, Any], expected: bool) -> None:
assert schema_utils.is_submitter_required(schema) == expected


@pytest.mark.parametrize(
"schema,expected",
[
({}, ""),
(STRING_SCHEMA, COMMENT),
],
)
def test_get_submission_comment(schema: Dict[str, Any], expected: str) -> None:
assert schema_utils.get_submission_comment(schema) == expected


@pytest.mark.parametrize(
"schema,expected",
[
({}, []),
(STRING_SCHEMA, EXAMPLE),
],
)
def test_get_submission_examples(schema: Dict[str, Any], expected: List[str]) -> None:
assert schema_utils.get_submission_examples(schema) == expected


@pytest.mark.parametrize(
"schema,expected",
[
({}, []),
(STRING_SCHEMA, ENUM),
],
)
def test_get_suggested_enum(schema: Dict[str, Any], expected: List[str]) -> None:
assert schema_utils.get_suggested_enum(schema) == expected


@pytest.mark.parametrize(
"schema,expected",
[
({}, {}),
(SCHEMA, DEPENDENT_REQUIRED),
],
)
def test_get_dependent_required(
schema: Dict[str, Any], expected: Dict[str, List[str]]
) -> None:
assert schema_utils.get_dependent_required(schema) == expected

0 comments on commit 538acd0

Please sign in to comment.