Source code for footprints.priorities

"""
Footprint utilities to handle the ``priority`` footprint's attribute.
"""

import functools

__all__ = ['top', ]


[docs]@functools.total_ordering class PriorityLevel: """Single level to be used inside footprints.""" def __init__(self, tagname, pset): self._tag = tagname if isinstance(pset, PrioritySet): self._pset = pset else: raise TypeError('argument `pset` should be a PrioritySet, not {!s}'.format(type(pset))) def __call__(self): return self.rank @property def tag(self): return self._tag @property def inset(self): return self._pset @property def rank(self): """Actual order level in the current set of priorities.""" return self.inset.levelindex(self.tag) def __eq__(self, other): if not isinstance(other, PriorityLevel): try: other = self.inset.level(str(other)) except (ValueError, TypeError): return False return self.rank == other.rank def __gt__(self, other): if not isinstance(other, PriorityLevel): other = self.inset.level(str(other)) return self.rank > other.rank
[docs] def delete(self): """Removes itself from the priority set.""" self.inset.remove(self.tag)
[docs] def up(self): """Gain one step in the ranking.""" return self.inset.rerank(self.tag, 1)
[docs] def down(self): """Loose one step in the ranking.""" return self.inset.rerank(self.tag, -1)
[docs] def top(self): """Rerank as the top level priority.""" return self.inset.rerank(self.tag, len(self.inset()))
[docs] def bottom(self): """Rerank as the bottom level priority.""" return self.inset.rerank(self.tag, -1 * len(self.inset()))
[docs] def addafter(self, tag): """Add a new priority after the current one.""" return self.inset.insert(tag, after=self.tag)
[docs] def addbefore(self, tag): """Add a new priority before the current one.""" return self.inset.insert(tag, before=self.tag)
[docs] def nextlevel(self): """Return the next priority level in the set... if any.""" return self.inset.levelbyindex(self.rank + 1)
[docs] def prevlevel(self): """Return the previous priority level in the set... if any.""" return self.inset.levelbyindex(self.rank - 1)
[docs] def as_dump(self): """Return a nicely formated class name for dump in footprint.""" return '{0.tag} (rank={0.rank:d})'.format(self)
[docs]class PrioritySet: """ Iterable class for handling unsortable priority levels. """ def __init__(self, levels=None): self._levels = list() if levels is not None: self.extend(*levels) self._freeze = dict(default=self._levels[:]) def __iter__(self): yield from self._levels def __call__(self): return tuple(self._levels) def __len__(self): return len(self._levels) def __contains__(self, item): try: item = item.tag except AttributeError: pass return item.upper() in self.levels @property def levels(self): return tuple(self._levels)
[docs] def level(self, tag): """Return the :class:`PriorityLevel` object of this set associated to the specified ``tag`` name.""" if isinstance(tag, PriorityLevel): return tag pl = None if tag and str(tag).upper() in self._levels: pl = self.__dict__[str(tag).upper()] return pl
[docs] def reset(self): """Restore the frozen defaults as defined at the initialisation phase.""" self.restore('default')
[docs] def freezed(self): """Return a tuple of tags used for naming past freezings.""" return sorted(self._freeze.keys())
[docs] def freeze(self, tag): """Store the current ordered list of priorities with a ``tag``.""" tag = tag.lower() if tag == 'default': raise ValueError('Could not freeze a new default') else: self._freeze[tag] = self._levels[:]
[docs] def restore(self, tag): """Restore previously frozen defaults under the specified ``tag``.""" self._levels = self._freeze[tag.lower()][:] for levelname in [x for x in self._levels if x not in self.__dict__]: self.__dict__[levelname] = PriorityLevel(levelname, pset=self)
[docs] def extend(self, *levels): """ Extends the set of logical names for priorities. Existing levels are reranked at top priority as well as new one. """ for levelname in [x.upper() for x in levels]: while levelname in self._levels: self._levels.remove(levelname) self._levels.append(levelname) self.__dict__[levelname] = PriorityLevel(levelname, pset=self)
[docs] def levelbyindex(self, ipos): """Returns the relative position of the priority named ``tag``.""" if ipos < 0 or ipos >= len(self._levels): return None else: return self.__dict__[self._levels[ipos]]
[docs] def levelindex(self, tag): """Returns the relative position of the priority named ``tag``.""" tag = tag.upper() if tag not in self._levels: raise ValueError('No such level priority: {!s}'.format(tag)) return self._levels.index(tag)
[docs] def rerank(self, tag, upd): """Reranks the priority named ``tag`` according to ``upd`` shift. Eg: +1, -2, etc.""" tag = tag.upper() ipos = self._levels.index(tag) + upd if ipos < 0: ipos = 0 self._levels.remove(tag) self._levels.insert(ipos, tag) return self.level(tag)
[docs] def remove(self, tag): """Remove the :class:`PriorityLevel` item associated to the specified ``tag`` name.""" if isinstance(tag, PriorityLevel): tag = tag.tag else: tag = str(tag).upper() self._levels.remove(tag) del self.__dict__[tag]
[docs] def insert(self, tag=None, after=None, before=None): """Insert a new priority after or before an other one (which the tag name is given).""" if tag is None: return None else: tag = str(tag).upper() self.extend(tag) if after is not None: self._levels.remove(tag) if isinstance(after, PriorityLevel): after = after.tag self._levels.insert(self._levels.index(after.upper()) + 1, tag) elif before is not None: self._levels.remove(tag) if isinstance(before, PriorityLevel): before = before.tag self._levels.insert(self._levels.index(before.upper()), tag) return self.level(tag)
#: Predefined ordered object. top = PrioritySet(levels=['none', 'default', 'toolbox', 'debug'])
[docs]def set_before(priorityref, *args): """Set ``args`` priority before specified ``priorityref``.""" for newpriority in args: top.insert(tag=newpriority, before=priorityref)
[docs]def set_after(priorityref, *args): """Set ``args`` priority after specified ``priorityref``.""" for newpriority in reversed(args): top.insert(tag=newpriority, after=priorityref)