Ejemplo n.º 1
0
    def __new__(metacls, clsname, bases, clsdict, **kwargs):
        if hasattr(clsdict, 'tags'):
            # ▼ Collect all base class tag dicts + current class tag dict
            tagDicts = filter(None, (parent.__dict__.get('__tags__')
                                     for parent in bases))
            tagsItems = (item
                         for tagsDict in attachItem(tagDicts, clsdict.tags)
                         for item in tagsDict.items())

            # ▼ Merge all tags by tag name
            newTags = {}
            getIndex = itemgetter(0)
            for k, g in groupby(sorted(tagsItems, key=getIndex), getIndex):
                newTags[k] = tuple(chain.from_iterable((i[1] for i in g)))

            # ▼ Check for name collisions
            for tagname, tags in newTags.items():
                if len(set(tags)) < len(tags):
                    raise AttributeError(
                        f"Class {clsname} has attr name conflict with base class in category {tagname}"
                        f" (test. name is: {(tag for tag in tags if tag not in set(tags)).__next__()}"
                    )
            clsdict['__tags__'] = newTags
        return super().__new__(metacls, clsname, bases, dict(clsdict),
                               **kwargs)
Ejemplo n.º 2
0
 def collectDefaults(bases, currentDefaults):
     dicts = attachItem(iterable=filter(None,
                                        (parent.__dict__.get('_defaults_')
                                         for parent in reversed(bases))),
                        append=currentDefaults)
     newDefaults = dicts.__next__().copy()
     for defaults in dicts:
         newDefaults.update(defaults)
     return newDefaults
Ejemplo n.º 3
0
    def mergeTags(parents, currentTags):
        # Collect all base class tags dicts + current class tags dict
        tagsDicts = attachItem(filter(None, (parent.__dict__.get('__tags__') for parent in parents)), currentTags)

        # Take main parent's tags as base tags dict
        try: newTags = tagsDicts.__next__().copy()

        # Use current tags if no single parent defines any
        except StopIteration: return currentTags

        # Merge all tags by tag name into 'newTags'
        for tagsDict in tagsDicts:
            reduceItems = ((tagname, newTags[tagname] | namesSet) for tagname, namesSet in tagsDict.items())
            for _ in starmap(partial(setitem, newTags), reduceItems): pass
            # TODO: Compare performance ▲ ▼, if negligible - replace with code below (more readable IMHO)
            # for tagname, updatedNamesSet in reduceItems:
            #     setitem(newTags, tagname, updatedNamesSet)
        return newTags
Ejemplo n.º 4
0
 def mergeParentDicts(parents, dictName, currentDict):
     dicts = attachItem(
             filter(None, (parent.__dict__.get(dictName) for parent in reversed(parents))), currentDict)
     newDict = dicts.__next__().copy()
     for attrDict in dicts: newDict.update(attrDict)
     return newDict