Source code for coalib.bearlib.aspects.collections
import itertools
import coalib.bearlib.aspects
from coalib.bearlib.aspects.meta import isaspect, issubaspect
from coalib.bearlib.aspects.base import aspectbase
[docs]class AspectList(list):
"""
List-derived container to hold aspects.
"""
def __init__(self, seq=(), exclude=None, languages=None):
"""
Initialize a new AspectList.
>>> from .Metadata import CommitMessage
>>> AspectList([CommitMessage.Shortlog, CommitMessage.Body])
[<aspectclass '...Shortlog'>, <aspectclass '...Body'>]
>>> AspectList(['Shortlog', 'CommitMessage.Body'])
[<aspectclass '...Shortlog'>, <aspectclass '...Body'>]
>>> AspectList([CommitMessage.Shortlog, 'CommitMessage.Body'])
[<aspectclass '...Shortlog'>, <aspectclass '...Body'>]
:param seq: A sequence containing either aspectclass, aspectclass
instance, or string of partial/full qualified aspect name.
:param exclude: A sequence of either aspectclass or string of aspect
name that marked as excluded from the list.
"""
super().__init__((item if isaspect(item) else
coalib.bearlib.aspects[item] for item in seq))
self.languages = languages
self.exclude = AspectList(exclude) if exclude is not None else []
def __contains__(self, aspect):
# Check if ``aspects`` language is supported.
if self.languages is not None and isinstance(aspect, aspectbase):
if aspect.language not in self.languages:
return False
for item in self:
if issubaspect(aspect, item):
return aspect not in self.exclude
return False
[docs] def get(self, aspect):
"""
Return first item that match or contain an aspect. See
:meth:`coalib.bearlib.aspects.aspectbase.get` for further example.
:param aspect: An aspectclass OR name of an aspect.
:return: An aspectclass OR aspectclass instance, depend on
AspectList content. Return None if no match found.
"""
if not isaspect(aspect):
aspect = coalib.bearlib.aspects[aspect]
if aspect in self.exclude:
return None
try:
return next(filter(None, (item.get(aspect) for item in self)))
except StopIteration:
return None
def _remove(self, item):
"""
Remove first matching item in list.
:param item: An aspectclass
:raises ValueError: When to be removed item is not found in list.
"""
for aspect in self:
if aspect is item or isinstance(aspect, item):
return super().remove(aspect)
raise ValueError('{}._remove(x): {} not in list.'
.format(type(self).__name__, item))
[docs] def get_leaf_aspects(self):
"""
Breakdown all of item in self into their leaf subaspects.
:return: An AspectList contain ONLY leaf aspects.
"""
aspects = type(self)()
for leaf_aspect in itertools.chain.from_iterable([
aspect.get_leaf_aspects() for aspect in self]):
# Make sure no duplication
if leaf_aspect not in aspects:
aspects.append(leaf_aspect)
for excluded_aspect in itertools.chain.from_iterable(
[aspect.get_leaf_aspects() for aspect in self.exclude]):
try:
aspects._remove(excluded_aspect)
except ValueError:
continue
return aspects