implement auto-renaming during merge, and change _merge() to support it
This commit is contained in:
parent
6f6143da1a
commit
3be4da3e7c
@ -429,7 +429,7 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def _merge(self, other: Mapping[str, 'Pattern'], key: str) -> None:
|
def _merge(self, key_self: str, other: Mapping[str, 'Pattern'], key_other: str) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def rename(self: ML, old_name: str, new_name: str) -> ML:
|
def rename(self: ML, old_name: str, new_name: str) -> ML:
|
||||||
@ -487,32 +487,39 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
|
|||||||
def add(
|
def add(
|
||||||
self: ML,
|
self: ML,
|
||||||
other: Mapping[str, 'Pattern'],
|
other: Mapping[str, 'Pattern'],
|
||||||
use_ours: Callable[[str], bool] = lambda name: False,
|
rename_theirs: Callable[['Library', str], str] = _rename_patterns,
|
||||||
use_theirs: Callable[[str], bool] = lambda name: False,
|
|
||||||
) -> ML:
|
) -> ML:
|
||||||
"""
|
"""
|
||||||
Add keys from another library into this one.
|
Add keys from another library into this one.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
other: The library to insert keys from
|
other: The library to insert keys from
|
||||||
use_ours: Decision function for name conflicts, called with pattern name.
|
rename_theirs: Called as rename_theirs(self, name) for each duplicate name
|
||||||
Should return `True` if the value from `self` should be used.
|
encountered in `other`. Should return the new name for the pattern in
|
||||||
use_theirs: Decision function for name conflicts. Same format as `use_ours`.
|
`other`.
|
||||||
Should return `True` if the value from `other` should be used.
|
Default is effectively
|
||||||
`use_ours` takes priority over `use_theirs`.
|
`name.split('$')[0] if name.startswith('_') else name`
|
||||||
Returns:
|
Returns:
|
||||||
self
|
self
|
||||||
"""
|
"""
|
||||||
duplicates = set(self.keys()) & set(other.keys())
|
duplicates = set(self.keys()) & set(other.keys())
|
||||||
keep_ours = set(name for name in duplicates if use_ours(name))
|
rename_map = {name: rename_theirs(self, name) for name in duplicates}
|
||||||
keep_theirs = set(name for name in duplicates - keep_ours if use_theirs(name))
|
renamed = set(rename_map.keys())
|
||||||
conflicts = duplicates - keep_ours - keep_theirs
|
|
||||||
|
|
||||||
|
if len(renamed) != len(rename_map):
|
||||||
|
raise LibraryError('Multiple `other` patterns have the same name after renaming!')
|
||||||
|
|
||||||
|
internal_conflicts = (set(other.keys()) - duplicates) & renamed
|
||||||
|
if internal_conflicts:
|
||||||
|
raise LibraryError('Renamed patterns conflict with un-renamed names in `other`' + pformat(internal_conflicts))
|
||||||
|
|
||||||
|
conflicts = set(self.keys()) & renamed
|
||||||
if conflicts:
|
if conflicts:
|
||||||
raise LibraryError('Unresolved duplicate keys encountered in library merge: ' + pformat(conflicts))
|
raise LibraryError('Unresolved duplicate keys encountered in library merge: ' + pformat(conflicts))
|
||||||
|
|
||||||
for key in set(other.keys()) - keep_ours:
|
for key in other.keys():
|
||||||
self._merge(other, key)
|
new_key = rename_map.get(key, key)
|
||||||
|
self._merge(new_key, other, key)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -692,7 +699,7 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
|
|||||||
|
|
||||||
new = type(self)()
|
new = type(self)()
|
||||||
for key in keep:
|
for key in keep:
|
||||||
new._merge(self, key)
|
new._merge(key, self, key)
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|
||||||
@ -758,8 +765,8 @@ class WrapLibrary(MutableLibrary):
|
|||||||
def __delitem__(self, key: str) -> None:
|
def __delitem__(self, key: str) -> None:
|
||||||
del self.mapping[key]
|
del self.mapping[key]
|
||||||
|
|
||||||
def _merge(self, other: Mapping[str, 'Pattern'], key: str) -> None:
|
def _merge(self, key_self: str, other: Mapping[str, 'Pattern'], key_other: str) -> None:
|
||||||
self[key] = other[key]
|
self[key_self] = other[key_other]
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f'<WrapLibrary ({type(self.mapping)}) with keys\n' + pformat(list(self.keys())) + '>'
|
return f'<WrapLibrary ({type(self.mapping)}) with keys\n' + pformat(list(self.keys())) + '>'
|
||||||
@ -830,16 +837,13 @@ class LazyLibrary(MutableLibrary):
|
|||||||
def __len__(self) -> int:
|
def __len__(self) -> int:
|
||||||
return len(self.dict)
|
return len(self.dict)
|
||||||
|
|
||||||
def set_const(self, key: str, value: 'Pattern') -> None:
|
def _merge(self, key_self: str, other: Mapping[str, 'Pattern'], key_other: str) -> None:
|
||||||
self[key] = lambda: value
|
|
||||||
|
|
||||||
def _merge(self, other: Mapping[str, 'Pattern'], key: str) -> None:
|
|
||||||
if isinstance(other, LazyLibrary):
|
if isinstance(other, LazyLibrary):
|
||||||
self.dict[key] = other.dict[key]
|
self.dict[key_self] = other.dict[key_other]
|
||||||
if key in other.cache:
|
if key_other in other.cache:
|
||||||
self.cache[key] = other.cache[key]
|
self.cache[key_self] = other.cache[key_other]
|
||||||
else:
|
else:
|
||||||
self.set_const(key, other[key])
|
self[key_self] = other[key_other]
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return '<LazyLibrary with keys\n' + pformat(list(self.keys())) + '>'
|
return '<LazyLibrary with keys\n' + pformat(list(self.keys())) + '>'
|
||||||
@ -902,3 +906,13 @@ class AbstractView(Mapping[str, Abstract]):
|
|||||||
|
|
||||||
def __len__(self) -> int:
|
def __len__(self) -> int:
|
||||||
return self.library.__len__()
|
return self.library.__len__()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _rename_patterns(lib: Library, name: str) -> str:
|
||||||
|
# TODO document rename function
|
||||||
|
if not name.startswith('_'):
|
||||||
|
return name
|
||||||
|
|
||||||
|
stem = name.split('$')[0]
|
||||||
|
return lib.get_name(stem)
|
||||||
|
Loading…
Reference in New Issue
Block a user