diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hydrilla/item_infos.py | 6 | ||||
-rw-r--r-- | src/hydrilla/proxy/simple_dependency_satisfying.py | 29 | ||||
-rw-r--r-- | src/hydrilla/proxy/state_impl/concrete_state.py | 72 |
3 files changed, 63 insertions, 44 deletions
diff --git a/src/hydrilla/item_infos.py b/src/hydrilla/item_infos.py index 9ba47bd..c1e1e31 100644 --- a/src/hydrilla/item_infos.py +++ b/src/hydrilla/item_infos.py @@ -151,7 +151,7 @@ class ItemIdentity: @dc.dataclass(frozen=True) # type: ignore[misc] class ItemInfoBase(ABC, ItemIdentity, Categorizable): """....""" - type_name: t.ClassVar[str] = '!INVALID!' + type_name: t.ClassVar[str] source_name: str = dc.field(hash=False) source_copyright: tuple[FileSpecifier, ...] = dc.field(hash=False) @@ -363,8 +363,8 @@ class MappingInfo(ItemInfoBase): # return (self.identifier, self.version, self.repository) < \ # (other.identifier, other.version, other.repository) - # class property - type_name = 'mapping' + +AnyInfo = t.Union[ResourceInfo, MappingInfo] LoadedType = t.TypeVar('LoadedType', ResourceInfo, MappingInfo) diff --git a/src/hydrilla/proxy/simple_dependency_satisfying.py b/src/hydrilla/proxy/simple_dependency_satisfying.py index 9716fe5..889ae98 100644 --- a/src/hydrilla/proxy/simple_dependency_satisfying.py +++ b/src/hydrilla/proxy/simple_dependency_satisfying.py @@ -57,7 +57,7 @@ ComputedPayloadsDict = dict[ empty_identifiers_set: set[str] = set() @dc.dataclass(frozen=True) -class ItemsCollection: +class _ItemsCollection: resources: t.Mapping[str, item_infos.ResourceInfo] mappings: t.Mapping[str, item_infos.MappingInfo] @@ -187,3 +187,30 @@ class ItemsCollection: computed_result.pop(self.mappings[identifier], None) return computed_result + +AnyInfoVar = t.TypeVar( + 'AnyInfoVar', + item_infos.ResourceInfo, + item_infos.MappingInfo +) + +def _choose_newest(infos: t.Iterable[AnyInfoVar]) -> dict[str, AnyInfoVar]: + best_versions: dict[str, AnyInfoVar] = {} + + for info in infos: + other = best_versions.setdefault(info.identifier, info) + + if (other.version, other.repo, info.repo_iteration) < \ + (info.version, info.repo, other.repo_iteration): + best_versions[info.identifier] = info + + return best_versions + +def compute_payloads( + resources: t.Iterable[item_infos.ResourceInfo], + mappings: t.Iterable[item_infos.MappingInfo] +) -> ComputedPayloadsDict: + best_resources = _choose_newest(resources) + best_mappings = _choose_newest(mappings) + + return _ItemsCollection(best_resources, best_mappings).compute_payloads() diff --git a/src/hydrilla/proxy/state_impl/concrete_state.py b/src/hydrilla/proxy/state_impl/concrete_state.py index cd6698c..1b46ae9 100644 --- a/src/hydrilla/proxy/state_impl/concrete_state.py +++ b/src/hydrilla/proxy/state_impl/concrete_state.py @@ -48,7 +48,7 @@ from ... import pattern_tree from ... import url_patterns from ... import versions from ... import item_infos -from ..simple_dependency_satisfying import ItemsCollection, ComputedPayload +from ..simple_dependency_satisfying import compute_payloads, ComputedPayload from .. import state as st from .. import policies from . import base @@ -56,8 +56,6 @@ from . import base here = Path(__file__).resolve().parent -AnyInfo = t.Union[item_infos.ResourceInfo, item_infos.MappingInfo] - @dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc] class ConcreteRepoRef(st.RepoRef): def remove(self, state: st.HaketiloState) -> None: @@ -316,7 +314,7 @@ def get_or_make_item_version( item_id: int, repo_iteration_id: int, definition: str, - info: AnyInfo + info: item_infos.AnyInfo ) -> int: ver_str = versions.version_string(info.version) @@ -419,6 +417,31 @@ def make_file_use( (item_version_id, file_id, name, type, mime_type, idx) ) +def get_infos_of_type(cursor: sqlite3.Cursor, info_type: t.Type[AnyInfoVar]) \ + -> t.Iterable[AnyInfoVar]: + cursor.execute( + ''' + SELECT + iv.definition, r.name, ri.iteration + FROM + item_versions AS iv + JOIN items AS i USING (item_id) + JOIN repo_iterations AS ri USING (repo_iteration_id) + JOIN repos AS r USING (repo_id) + WHERE + i.type = ?; + ''', + (info_type.type_name[0].upper(),) + ) + + result: list[AnyInfoVar] = [] + + for definition, repo_name, repo_iteration in cursor.fetchall(): + definition_io = io.StringIO(definition) + result.append(info_type.load(definition_io, repo_name, repo_iteration)) + + return result + @dc.dataclass class ConcreteHaketiloState(base.HaketiloStateWithFields): def __post_init__(self) -> None: @@ -474,7 +497,7 @@ class ConcreteHaketiloState(base.HaketiloStateWithFields): with self.cursor(lock=True, transaction=True) as cursor: for info_type in [item_infos.ResourceInfo, item_infos.MappingInfo]: - info: AnyInfo + info: item_infos.AnyInfo for info, definition in read_items( malcontent_dir_path, info_type # type: ignore @@ -551,45 +574,14 @@ class ConcreteHaketiloState(base.HaketiloStateWithFields): ) def rebuild_structures(self, cursor: sqlite3.Cursor) -> None: - cursor.execute( - ''' - SELECT - item_id, type, version, definition - FROM - item_versions JOIN items USING (item_id); - ''' - ) - - best_versions: dict[int, versions.VerTuple] = {} - definitions = {} - types = {} - - for item_id, item_type, ver_str, definition in cursor.fetchall(): - # TODO: what we're doing in this loop does not yet take different - # repos and different repo iterations into account. - ver = versions.parse_normalize_version(ver_str) - if best_versions.get(item_id, (0,)) < ver: - best_versions[item_id] = ver - definitions[item_id] = definition - types[item_id] = item_type - - resources = {} - mappings = {} - - for item_id, definition in definitions.items(): - if types[item_id] == 'R': - r_info = item_infos.ResourceInfo.load(io.StringIO(definition)) - resources[r_info.identifier] = r_info - else: - m_info = item_infos.MappingInfo.load(io.StringIO(definition)) - mappings[m_info.identifier] = m_info + resources = get_infos_of_type(cursor, item_infos.ResourceInfo) + mappings = get_infos_of_type(cursor, item_infos.MappingInfo) - items_collection = ItemsCollection(resources, mappings) - computed_payloads = items_collection.compute_payloads() + payloads = compute_payloads(resources, mappings) payloads_data = {} - for mapping_info, by_pattern in computed_payloads.items(): + for mapping_info, by_pattern in payloads.items(): for num, (pattern, payload) in enumerate(by_pattern.items()): payload_id = f'{num}@{mapping_info.identifier}' |