diff --git a/CHANGELOG.md b/CHANGELOG.md index e97c244..b046206 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Restore jsonschema's type validator, as its performance has improved in recent Python versions https://github.com/OpenDataServices/lib-cove/pull/127 - Allow `SchemaJsonMixin` classes to define a `validator` method, that accepts lib-cove's JSON Schema draft 4 validator class and its format checker, and returns a validator instance. https://github.com/OpenDataServices/lib-cove/pull/128 +### Fixed + +- Calculate additional codelist values for schema using `anyOf`, like OCDS record packages https://github.com/open-contracting/lib-cove-ocds/issues/106 + ## [0.31.0] - 2023-07-06 ### Changed diff --git a/libcove/lib/common.py b/libcove/lib/common.py index 016677d..0939a73 100644 --- a/libcove/lib/common.py +++ b/libcove/lib/common.py @@ -456,17 +456,26 @@ def get_schema_codelist_paths( if "codelist" in value and path not in codelist_paths: codelist_paths[path] = (value["codelist"], value.get("openCodelist", False)) - if value.get("type") == "object": - get_schema_codelist_paths(None, value, path, codelist_paths) - elif value.get("type") == "array" and isinstance(value.get("items"), dict): - if value.get("items").get("type") == "string": - if "codelist" in value["items"] and path not in codelist_paths: - codelist_paths[path] = ( - value["items"]["codelist"], - value["items"].get("openCodelist", False), + descendants = [] + if "oneOf" in value and isinstance(value["oneOf"], list): + descendants = value["oneOf"] + else: + descendants = [value] + + for value in descendants: + if value.get("type") == "object": + get_schema_codelist_paths(None, value, path, codelist_paths) + elif value.get("type") == "array" and isinstance(value.get("items"), dict): + if value.get("items").get("type") == "string": + if "codelist" in value["items"] and path not in codelist_paths: + codelist_paths[path] = ( + value["items"]["codelist"], + value["items"].get("openCodelist", False), + ) + elif value.get("items").get("properties"): + get_schema_codelist_paths( + None, value["items"], path, codelist_paths ) - elif value.get("items").get("properties"): - get_schema_codelist_paths(None, value["items"], path, codelist_paths) return codelist_paths diff --git a/tests/lib/fixtures/common/schema_with_oneof_codelists.json b/tests/lib/fixtures/common/schema_with_oneof_codelists.json new file mode 100644 index 0000000..b0a0068 --- /dev/null +++ b/tests/lib/fixtures/common/schema_with_oneof_codelists.json @@ -0,0 +1,46 @@ +{ + "id": "bods-package.json", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "data": { + "oneOf": [ + { + "type": "object", + "properties": { + "entityType": { + "enum": [ + "registeredEntity", + "legalEntity", + "arrangement", + "anonymousEntity", + "unknownEntity" + ], + "openCodelist": false, + "title": "Type", + "type": "string", + "codelist": "currency.csv" + } + } + }, + { + "type": "object", + "properties": { + "entityType": { + "enum": [ + "registeredEntity", + "legalEntity", + "arrangement", + "anonymousEntity", + "unknownEntity" + ], + "type": "string" + } + } + } + ] + } + }, + "type": "array", + "version": "0.1" +} diff --git a/tests/lib/test_common.py b/tests/lib/test_common.py index fd4ae36..a799150 100644 --- a/tests/lib/test_common.py +++ b/tests/lib/test_common.py @@ -1347,3 +1347,32 @@ def test_get_additional_codelist_values(): "extension_codelist": False, }, } + + +def test_get_additional_codelist_values_anyOf(): + json_data = {"data": {"entityType": "additional"} } + + schema_obj = SchemaJsonMixin() + schema_obj.schema_host = os.path.join( + os.path.dirname(os.path.realpath(__file__)), "fixtures", "common/" + ) + schema_obj.release_pkg_schema_name = f"schema_with_oneof_codelists.json" + schema_obj.pkg_schema_url = os.path.join( + schema_obj.schema_host, schema_obj.release_pkg_schema_name + ) + schema_obj.codelists = "https://raw.githubusercontent.com/open-contracting/standard/1.1/schema/codelists/" + + additional_codelist_values = get_additional_codelist_values(schema_obj, json_data) + + assert additional_codelist_values == { + 'data/entityType': { + 'path': 'data', + 'field': 'entityType', + 'codelist': 'currency.csv', + 'codelist_url': 'https://raw.githubusercontent.com/open-contracting/standard/1.1/schema/codelists/currency.csv', + 'codelist_amend_urls': [], + 'isopen': False, + 'values': ['additional'], + 'extension_codelist': False + } + }