redo library merging

This commit is contained in:
Jan Petykiewicz 2023-02-08 08:44:36 -08:00
parent c6b8027b4d
commit 492565c1a6

View File

@ -524,14 +524,14 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
return name return name
def add( def add(
self: ML, self,
other: Mapping[str, 'Pattern'], other: Mapping[str, 'Pattern'],
rename_theirs: Callable[['Library', str], str] = _rename_patterns, rename_theirs: Callable[['Library', str], str] = _rename_patterns,
) -> ML: ) -> Dict[str, str]:
""" """
Add keys from another library into this one. Add keys from another library into this one.
# TODO explain reference renaming # TODO explain reference renaming and return
Args: Args:
other: The library to insert keys from other: The library to insert keys from
@ -544,33 +544,32 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
self self
""" """
duplicates = set(self.keys()) & set(other.keys()) duplicates = set(self.keys()) & set(other.keys())
rename_map = {name: rename_theirs(self, name) for name in duplicates}
renamed = set(rename_map.keys())
if len(renamed) != len(rename_map): if not duplicates:
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()) & set(rename_map.values())
if conflicts:
raise LibraryError('Unresolved duplicate keys encountered in library merge: ' + pformat(conflicts))
if rename_map:
temp = WrapLibrary(copy.deepcopy(dict(other))) # Copy and turn into a mutable library
for old_name, new_name in rename_map.items():
temp.rename(old_name, new_name, move_references=True)
for key in temp.keys():
self._merge(key, temp, key)
else:
for key in other.keys(): for key in other.keys():
self._merge(key, other, key) self._merge(key, other, key)
return {}
return self temp = WrapLibrary(copy.deepcopy(dict(other))) # TODO maybe add a `mutate` arg? Might want to keep the same patterns
rename_map = {}
for old_name in temp:
if old_name in duplicates:
new_name = rename_theirs(self, old_name)
if new_name in self:
raise LibraryError(f'Unresolved duplicate key encountered in library merge: {old_name} -> {new_name}')
rename_map[old_name] = new_name
else:
new_name = old_name
self._merge(new_name, temp, old_name)
# Update references in the newly-added cells
for old_name in temp:
new_name = rename_map.get(old_name, old_name)
for ref in self[new_name].refs:
ref.target = rename_map.get(ref.target, ref.target)
return rename_map
def add_tree( def add_tree(
self, self,
@ -600,8 +599,8 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
tree.library.rename(tree.top, name, move_references=True) tree.library.rename(tree.top, name, move_references=True)
tree.top = name tree.top = name
self.add(tree.library, rename_theirs=rename_theirs) rename_map = self.add(tree.library, rename_theirs=rename_theirs)
return name return rename_map.get(name, name)
def __lshift__(self, other: Mapping[str, 'Pattern']) -> str: def __lshift__(self, other: Mapping[str, 'Pattern']) -> str:
if isinstance(other, Tree): if isinstance(other, Tree):