Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions codelists/hierarchy.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ def __init__(self, root, edges):
self._descendants_cache = {}
self._ancestors_cache = {}

def __eq__(self, other):
"""Compare hierarchies excluding cache items, resolving possible deserialisation differences"""

def resolve_deser_nulls(_dict):
return {k or "null": {i or "null" for i in v} for k, v in _dict.items()}

return (
self.root == other.root
and self.nodes == other.nodes
and resolve_deser_nulls(self.child_map)
== resolve_deser_nulls(other.child_map)
and resolve_deser_nulls(self.parent_map)
== resolve_deser_nulls(other.parent_map)
)

@classmethod
def from_codes(cls, coding_system, codes):
"""Build a hierarchy containing the given codes, and their ancestors/descendants
Expand Down
15 changes: 2 additions & 13 deletions coding_systems/base/import_data_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import json
import shutil
from itertools import islice
from pathlib import Path
Expand Down Expand Up @@ -339,11 +338,6 @@ def _check_version_by_hierarchy(coding_system, version):
and identical hierarchies.
"""

def _hierarchy_excl_cache_items(hierarchy):
# `_descendants_cache` and `_ancestors_cache` will not have been generated for the
# new hierarchy
return {k: v for k, v in hierarchy.items() if not k.endswith("_cache")}

# All codelist versions that existed prior to implementation of coding system releases
# have an "unknown" coding system release, which represents the coding system data at that
# point. For older codelist versions, that is not the actual coding system release that was
Expand All @@ -352,13 +346,8 @@ def _hierarchy_excl_cache_items(hierarchy):
# All existing codelist versions, including those with the "unknown" coding system release,
# will have a cached hierarchy, built with the original coding system release.
# We compare this to a hierarchy built from the same codes, but with the new release.
original_hierarchy_data = _hierarchy_excl_cache_items(
json.loads(version.cached_hierarchy.data)
)
new_hierarchy_data = _hierarchy_excl_cache_items(
json.loads(Hierarchy.from_codes(coding_system, version.codes).data_for_cache())
)
return original_hierarchy_data == new_hierarchy_data

return version.hierarchy == Hierarchy.from_codes(coding_system, version.codes)


def _check_version_by_search(coding_system, version):
Expand Down
44 changes: 44 additions & 0 deletions coding_systems/base/tests/test_import_data_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
from datetime import datetime

import pytest
Expand Down Expand Up @@ -323,3 +324,46 @@ def test_save_codelist_draft_updates_compatibility_multiple_releases(self):
self.bnf_version_with_search.compatible_releases.first().database_alias
== "bnf_import-data_20220901"
)


class TestUpdateCodelistVersionCompatibilityIsOrderInsensitive(
BaseCodingSystemDynamicDatabaseTestCase
):
db_aliases = [
"bnf_import-data_20221101",
]

@pytest.mark.usefixtures("_get_bnf_release", "_get_bnf_review_version_with_search")
def test_update_codelist_version_compatibility_is_order_insensitive(
self,
):
# modify the cached hierarchy data such that order of list elements is reversed
modified_existing_cached_hierarchy = json.loads(
self.bnf_review_version_with_search.cached_hierarchy.data
)
modified_existing_cached_hierarchy["nodes"] = list(
reversed(modified_existing_cached_hierarchy["nodes"])
)
modified_existing_cached_hierarchy["child_map"] = {
k: list(reversed(v))
for k, v in modified_existing_cached_hierarchy["child_map"].items()
}
modified_existing_cached_hierarchy["parent_map"] = {
k: list(reversed(v))
for k, v in modified_existing_cached_hierarchy["parent_map"].items()
}
modified_existing_cached_hierarchy_data = json.dumps(
modified_existing_cached_hierarchy
)
assert (
modified_existing_cached_hierarchy_data
!= self.bnf_review_version_with_search.cached_hierarchy.data
)

self.bnf_review_version_with_search.cached_hierarchy.data = (
modified_existing_cached_hierarchy_data
)
self.bnf_review_version_with_search.cached_hierarchy.save()

update_codelist_version_compatibility("bnf", self.bnf_release.database_alias)
assert self.bnf_review_version_with_search.compatible_releases.exists()