Ejemplo n.º 1
0
 def __init__(self, origin, cls, name, doc=None):
     Dispatcher.__init__(self, name, doc)
     self.origin = origin
     self.obj = None
     # Copy standard and lambda functions
     standard_funcs = origin.standard_funcs.copy()
     lambda_funcs = origin.lambda_funcs.copy()
     # Add all functions from ancestor classes
     for base_cls in inspect.getmro(cls):
         if base_cls is cls:
             continue
         if hasattr(base_cls, name):
             parent_func = getattr(base_cls, name)
             if isinstance(parent_func, MethodDispatcher):
                 parent_func = parent_func.origin
                 for (parent_standard_key_i, parent_standard_func_i
                      ) in parent_func.standard_funcs.items():
                     if parent_standard_key_i not in standard_funcs:
                         standard_funcs[
                             parent_standard_key_i] = parent_standard_func_i
                 for (parent_lambda_key_i, parent_lambda_func_i
                      ) in parent_func.lambda_funcs.items():
                     if parent_lambda_key_i not in lambda_funcs:
                         lambda_funcs[
                             parent_lambda_key_i] = parent_lambda_func_i
             elif ismethod(parent_func) and not hasattr(
                     parent_func, "__isabstractmethod__"):
                 parent_signature = (
                     len(inspect.signature(parent_func).parameters) -
                     1) * (object, )
                 parent_standard_key = (parent_signature, parent_signature)
                 if parent_standard_key not in standard_funcs:
                     standard_funcs[parent_standard_key] = parent_func
             else:
                 pass  # This happens with slot wrapper, method wrapper and method descriptor types for builtin objects
     # Add all standard functions
     for (key, func) in standard_funcs.items():
         self._add(key[0], key[1], func)
     # Add all lambda functions
     # NOTE: it is not possible to change the underlying type returned by lambda after this loop has been processed
     for (signature_lambda, lambda_func) in lambda_funcs.items():
         signature = tuple([
             typ(cls) if islambda(typ) else typ for typ in signature_lambda
         ])
         self._add(signature, signature, lambda_func)
     # Trigger reordering, if needed
     self._cache.clear()
     try:
         del self._ordering
     except AttributeError:
         pass
 def _(func_or_class):
     nonlocal name
     name = func_or_class.__name__ if name is None else name
     is_class = inspect.isclass(func_or_class)
     is_method = not is_class and ismethod(func_or_class)
     module = inspect.getmodule(func_or_class)
     
     nonlocal types
     if len(types) == 0:
         assert is_method or not is_class # is method or function
         signature = inspect.signature(func_or_class)
         annotations = tuple(param_value.annotation for (param_name, param_value) in signature.parameters.items() if param_value.kind in (inspect.Parameter.POSITIONAL_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD))
         if is_method:
             annotations = annotations[1:] # throw self away
         assert all(ann is not inspect.Parameter.empty for ann in annotations)
         types = annotations
     if is_method or not is_class: # is method or function
         signature = inspect.signature(func_or_class)
         assert len(types) == len(tuple(param_name for (param_name, param_value) in signature.parameters.items() if param_value.kind in (inspect.Parameter.POSITIONAL_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD))) - (1 if is_method else 0) # throw self away
     
     if is_method:
         assert module_kwarg is None
         assert replaces is None
         assert replaces_if is None
         frame = inspect.currentframe()
         for _ in range(frame_back_times):
             frame = frame.f_back
         dispatcher = frame.f_locals.get(name, MethodDispatcher_Wrapper(name))
         dispatcher.add(types, func_or_class)
         return dispatcher
     else: # is function or class
         if is_class:
             assert module_kwarg is not None
             assert module_kwarg is not module # otherwise module.name is not a class anymore but a function
             module = module_kwarg
         else:
             if module_kwarg is None:
                 pass # we would like to store the dispatched function in its module, rather than the original one
             else:
                 module = module_kwarg # we would like to store the original function in its module and the dispatched in module_kwarg
         if not hasattr(module, name):
             setattr(module, name, Dispatcher(name))
         dispatcher = getattr(module, name)
         assert isinstance(dispatcher, Dispatcher)
         dispatcher.add(types, func_or_class, replaces=replaces, replaces_if=replaces_if)
         if module_kwarg is None:
             return dispatcher
         else:
             return func_or_class