def __init__(self, op_str, event_checkers, check=True, prefix_str=''): super().__init__(check=check) checker_list = [] optional_checker_list = [] for checker in event_checkers: # "unwrap" checkers of the same type, to avoid useless levels of # nesting. This is valid since the operator is known to be # associative. We don't use isinstance to avoid merging checkers # that may have different semantics. if type(checker) is type(self): checker_list.extend(checker.checkers) # Aggregate them separately to avoid having multiple of them elif isinstance(checker, OptionalTraceEventChecker): optional_checker_list.append(checker) else: checker_list.append(checker) if optional_checker_list: checker_list.append( OptionalTraceEventChecker(optional_checker_list)) # Avoid having the same event twice at the same level def key(checker): if isinstance(checker, TraceEventChecker): return checker.event else: return checker checker_list = deduplicate(checker_list, key=key) self.checkers = checker_list self.op_str = op_str self.prefix_str = prefix_str
def _df_format(self, df): tag_cols = self._restrict_cols(self._stat_tag_cols, df) # Group together lines for each given tag df = df.sort_values(by=tag_cols, ignore_index=True) # Reorder columns cols = deduplicate( deduplicate( tag_cols + [ self._stat_col, self._val_col, self._unit_col, self._control_var_col, self._mean_kind_col ], keep_last=True, ) + list(df.columns), keep_last=False, ) return df[[col for col in cols if col in df.columns]]
def __new__(cls, name, bases, dct, *args, types=None, **kwargs): try: typeclass = bases[0] # That's TypeClass itself except IndexError: return super().__new__(cls, name, bases, dct, *args, **kwargs) # That's a typeclass being defined if types is None: dct.update( INSTANCES={}, DEFAULTS={}, REQUIRED=dict(), ) superclasses = deduplicate(bases, keep_last=False) with contextlib.suppress(ValueError): superclasses.remove(TypeClass) dct['SUPERCLASSES'] = superclasses for typeclass in superclasses: conflicting = { name for name in dct['REQUIRED'].keys() & typeclass.REQUIRED.keys() # If required method was specified in a base typeclass that # happens to be shared, there is no problem if dct['REQUIRED'][name] is not typeclass.REQUIRED[name] } if conflicting: def flatten(l): return list(itertools.chain.from_iterable(l)) # DFS traversal of superclass hierarchy, removing # intermediate node that are just there to merge parent # nodes without adding anything else. This avoids having # intermediate classes created by __and__ for example, for # better error reporting. def expand(superclass): # If that typeclass is an empty shim that just combines other typeclasses if not (superclass.__dict__.keys() - _EmptyTypeClass.__dict__.keys()): return flatten(map(expand, superclass.SUPERCLASSES)) else: return [superclass] superclasses = flatten(map(expand, superclasses)) superclasses = deduplicate(superclasses, keep_last=False) def format_method(name): return '{} (defined in: {} and {})'.format( name, dct['REQUIRED'][name].__qualname__, typeclass.REQUIRED[name].__qualname__, ) raise TypeError( 'Cannot merge typeclasses {} since the following methods conflict: {}' .format( ', '.join( sorted(tp.__qualname__ for tp in superclasses)), ', '.join(map(format_method, sorted(conflicting))), )) else: dct['DEFAULTS'].update(typeclass.DEFAULTS) dct['REQUIRED'].update(typeclass.REQUIRED) typeclass = super().__new__(cls, name, bases, dct, *args, **kwargs) typeclass.REQUIRED.update({ name: typeclass for name, attr in dct.items() if getattr(attr, '__required__', False) }) not_copied = set(dict(inspect.getmembers(_EmptyTypeClass)).keys()) not_copied |= dct['REQUIRED'].keys() | {'__qualname__', '__name__'} typeclass.DEFAULTS.update({ attr: val for attr, val in dct.items() if attr not in not_copied }) return typeclass # Someone tries to inherit from the typeclass to make an instance else: if len(bases) != 1: raise TypeError( 'A typeclass instance can only implement the methods of one typeclass, but multiple typeclasses were provided: {}' .format(', '.join( sorted(base.__qualname__ for base in bases)))) missing = typeclass.REQUIRED.keys() - dct.keys() if missing: raise NotImplementedError( 'Following methods are missing in {} instance and must be defined for instances of the {} typeclass: {}' .format( name, typeclass.__name__, ', '.join(sorted(missing)), )) # Merge-in the typeclass default implementations before using it, # so each instance contains all the methods of the typeclass dct = {**typeclass.DEFAULTS, **dct} types = types if isinstance(types, Iterable) else [types] for type_ in types: # Create an instance for each type, with the type as base class. bases = (type_, ) try: instance = type(name, bases, dct, *args, **kwargs) # Some classes like bool cannot be subclassed. Work around by # listing all their attributes and making a new class that has # all of them. except TypeError: total_dct = {**dict(inspect.getmembers(type_)), **dct} instance = type(name, tuple(), total_dct, *args, **kwargs) typeclass.INSTANCES[type_] = (instance, dct) # Monkey patch the types so that the typeclass methods can be # called "natively" on them if wanted get_top_package = lambda mod: mod.split('.')[0] # Only add the attribute if it does not exist already on the # target class def update_attr(attr, val): if not hasattr(type_, attr): setattr(type_, attr, val) # If the instance is declared in the same top-level package, # update the type itself. This prevents foreign packages from # monkey patching types but allows instances anywhere in a # given package if get_top_package(type_.__module__) == dct['__module__']: # Then the attributes defined in the instance for attr, val in dct.items(): update_attr(attr, val) # We scavanged all what we needed, the class has just been used to # as a vehicle to create a scope but will not be used directly. It # will still live a secrete life internally for casting though. # # Instead, return a class that is equivalent to the typeclass but # with the docstring of the instance. This allows Sphinx to pick up # the instance's docstring. dct = {**dct, **{'__doc__': dct.get('__doc__')}} return type(name, (typeclass, ), dct)