diff options
| author | Sefa Eyeoglu <contact@scrumplex.net> | 2022-06-26 12:16:11 +0200 |
|---|---|---|
| committer | Sefa Eyeoglu <contact@scrumplex.net> | 2022-06-26 12:16:11 +0200 |
| commit | 75006147ddc166ed3f6f148940018475159bd326 (patch) | |
| tree | cca8c90154e467f33763ed67d354d9859b3968f9 /meta | |
| parent | d5e359508bbec270fe81191b6eb209998559cc20 (diff) | |
| download | Project-Tick-75006147ddc166ed3f6f148940018475159bd326.tar.gz Project-Tick-75006147ddc166ed3f6f148940018475159bd326.zip | |
feat: implement merge function for MetaBase
Diffstat (limited to 'meta')
| -rw-r--r-- | meta/common/__init__.py | 19 | ||||
| -rw-r--r-- | meta/model/__init__.py | 37 |
2 files changed, 55 insertions, 1 deletions
diff --git a/meta/common/__init__.py b/meta/common/__init__.py index 8e463f8448..ee294f00b3 100644 --- a/meta/common/__init__.py +++ b/meta/common/__init__.py @@ -49,3 +49,22 @@ def replace_old_launchermeta_url(url): return o._replace(netloc="piston-meta.mojang.com").geturl() return url + + +def get_all_bases(cls, bases=None): + bases = bases or [] + bases.append(cls) + for c in cls.__bases__: + get_all_bases(c, bases) + return tuple(bases) + + +def merge_dict(base: dict, overlay: dict): + for k, v in base.items(): + if isinstance(v, dict): + merge_dict(v, overlay.setdefault(k, {})) + else: + if k not in overlay: + overlay[k] = v + + return overlay diff --git a/meta/model/__init__.py b/meta/model/__init__.py index b089040ee8..caa0e6d893 100644 --- a/meta/model/__init__.py +++ b/meta/model/__init__.py @@ -1,10 +1,11 @@ +import copy from datetime import datetime from typing import Optional, List, Dict, Any, Iterator import pydantic from pydantic import Field, validator -from ..common import serialize_datetime, replace_old_launchermeta_url +from ..common import serialize_datetime, replace_old_launchermeta_url, get_all_bases, merge_dict META_FORMAT_VERSION = 1 @@ -119,6 +120,40 @@ class MetaBase(pydantic.BaseModel): with open(file_path, "w") as f: f.write(self.json()) + def merge(self, other): + """ + Merge other object with self. + - Concatenates lists + - Combines sets + - Merges dictionaries (other takes priority) + - Recurses for all fields that are also MetaBase classes + - Overwrites for any other field type (int, string, ...) + """ + assert type(other) is type(self) + for key, field in self.__fields__.items(): + ours = getattr(self, key) + theirs = getattr(other, key) + if theirs is None: + continue + if ours is None: + setattr(self, key, theirs) + continue + + if isinstance(ours, list): + ours += theirs + elif isinstance(ours, set): + ours |= theirs + elif isinstance(ours, dict): + result = merge_dict(ours, copy.deepcopy(theirs)) + setattr(self, key, result) + elif MetaBase in get_all_bases(field.type_): + ours.merge(theirs) + else: + setattr(self, key, theirs) + + def __hash__(self): + return hash(self.json()) + class Config: allow_population_by_field_name = True |
