[PortPather] complain if the user gives ambiguous port names

This commit is contained in:
Jan Petykiewicz 2026-04-01 22:47:22 -07:00
commit b3a1489258
2 changed files with 69 additions and 7 deletions

View file

@ -857,20 +857,46 @@ class PortPather:
self.ports = [pp for pp in self.ports if pp not in ports_set]
return self
def _normalize_copy_map(self, name: str | Mapping[str, str], action: str) -> dict[str, str]:
if isinstance(name, str):
if len(self.ports) > 1:
raise BuildError(f'Use a mapping to {action} >1 port')
name_map = {self.ports[0]: name}
else:
name_map = dict(name)
missing_selected = set(name_map) - set(self.ports)
if missing_selected:
raise PortError(f'Can only {action} selected ports: {missing_selected}')
missing_pattern = set(name_map) - set(self.pather.pattern.ports)
if missing_pattern:
raise PortError(f'Ports to {action} were not found: {missing_pattern}')
targets = list(name_map.values())
duplicate_targets = {vv for vv in targets if targets.count(vv) > 1}
if duplicate_targets:
raise PortError(f'{action.capitalize()} targets would collide: {duplicate_targets}')
overwritten = {
dst for src, dst in name_map.items()
if dst in self.pather.pattern.ports and dst != src
}
if overwritten:
raise PortError(f'{action.capitalize()} would overwrite existing ports: {overwritten}')
return name_map
def mark(self, name: str | Mapping[str, str]) -> Self:
""" Bookmark current port(s). """
name_map: Mapping[str, str] = {self.ports[0]: name} if isinstance(name, str) else name
if isinstance(name, str) and len(self.ports) > 1:
raise BuildError('Use a mapping to mark >1 port')
name_map = self._normalize_copy_map(name, 'mark')
for src, dst in name_map.items():
self.pather.pattern.ports[dst] = self.pather.pattern[src].copy()
return self
def fork(self, name: str | Mapping[str, str]) -> Self:
""" Split and follow new name. """
name_map: Mapping[str, str] = {self.ports[0]: name} if isinstance(name, str) else name
if isinstance(name, str) and len(self.ports) > 1:
raise BuildError('Use a mapping to fork >1 port')
name_map = self._normalize_copy_map(name, 'fork')
for src, dst in name_map.items():
self.pather.pattern.ports[dst] = self.pather.pattern[src].copy()
self.ports = [(dst if pp == src else pp) for pp in self.ports]