def decorator(implementation): if verify: verify_matching_signatures(implementation, dispatcher) if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) # Equivalently, we could define this function directly instead of using # exec. This version has the advantage of giving the helper function a # more interpettable name. Otherwise, the original function does not # show up at all in many cases, e.g., if it's written in C or if the # dispatcher gets an invalid keyword argument. source = _wrapped_func_source.format(name=implementation.__name__) source_object = compile(source, filename='<__array_function__ internals>', mode='exec') scope = { 'implementation': implementation, 'dispatcher': dispatcher, 'functools': functools, 'implement_array_function': implement_array_function, } exec(source_object, scope) public_api = scope[implementation.__name__] if module is not None: public_api.__module__ = module public_api._implementation = implementation return public_api
def decorator(implementation): if verify: verify_matching_signatures(implementation, dispatcher) if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) @functools.wraps(implementation) def public_api(*args, **kwargs): relevant_args = dispatcher(*args, **kwargs) return implement_array_function( implementation, public_api, relevant_args, args, kwargs) if module is not None: public_api.__module__ = module return public_api
def decorator(implementation): if verify: verify_matching_signatures(implementation, dispatcher) if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) @functools.wraps(implementation) def public_api(*args, **kwargs): try: relevant_args = dispatcher(*args, **kwargs) except TypeError as exc: # Try to clean up a signature related TypeError. Such an # error will be something like: # dispatcher.__name__() got an unexpected keyword argument # # So replace the dispatcher name in this case. In principle # TypeErrors may be raised from _within_ the dispatcher, so # we check that the traceback contains a string that starts # with the name. (In principle we could also check the # traceback length, as it would be deeper.) msg = exc.args[0] disp_name = dispatcher.__name__ if not isinstance(msg, str) or not msg.startswith(disp_name): raise # Replace with the correct name and re-raise: new_msg = msg.replace(disp_name, public_api.__name__) raise TypeError(new_msg) from None return implement_array_function(implementation, public_api, relevant_args, args, kwargs) public_api.__code__ = public_api.__code__.replace( co_name=implementation.__name__, co_filename='<__array_function__ internals>') if module is not None: public_api.__module__ = module public_api._implementation = implementation return public_api
def decorator(implementation): if verify: verify_matching_signatures(implementation, dispatcher) if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) @functools.wraps(implementation) def public_api(*args, **kwargs): relevant_args = dispatcher(*args, **kwargs) return implement_array_function(implementation, public_api, relevant_args, args, kwargs) if module is not None: public_api.__module__ = module # TODO: remove this when we drop Python 2 support (functools.wraps) # adds __wrapped__ automatically in later versions) public_api.__wrapped__ = implementation return public_api
def decorator(implementation): if verify: verify_matching_signatures(implementation, dispatcher) if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) @functools.wraps(implementation) def public_api(*args, **kwargs): relevant_args = dispatcher(*args, **kwargs) return implement_array_function( implementation, public_api, relevant_args, args, kwargs) if module is not None: public_api.__module__ = module # TODO: remove this when we drop Python 2 support (functools.wraps # adds __wrapped__ automatically in later versions) public_api.__wrapped__ = implementation return public_api
def decorator(implementation): if verify: verify_matching_signatures(implementation, dispatcher) if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) @functools.wraps(implementation) def public_api(*args, **kwargs): relevant_args = dispatcher(*args, **kwargs) return implement_array_function(implementation, public_api, relevant_args, args, kwargs) public_api.__code__ = public_api.__code__.replace( co_name=implementation.__name__, co_filename='<__array_function__ internals>') if module is not None: public_api.__module__ = module public_api._implementation = implementation return public_api
def decorator(implementation): if verify: verify_matching_signatures(implementation, dispatcher) if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) # Equivalently, we could define this function directly instead of using # exec. This version has the advantage of giving the helper function a # more interpettable name. Otherwise, the original function does not # show up at all in many cases, e.g., if it's written in C or if the # dispatcher gets an invalid keyword argument. source = textwrap.dedent(""" @functools.wraps(implementation) def {name}(*args, **kwargs): relevant_args = dispatcher(*args, **kwargs) return implement_array_function( implementation, {name}, relevant_args, args, kwargs) """).format(name=implementation.__name__) source_object = compile(source, filename="<__array_function__ internals>", mode="exec") scope = { "implementation": implementation, "dispatcher": dispatcher, "functools": functools, "implement_array_function": implement_array_function, } exec(source_object, scope) public_api = scope[implementation.__name__] if module is not None: public_api.__module__ = module public_api._implementation = implementation return public_api
def decorator(implementation): if verify: verify_matching_signatures(implementation, dispatcher) if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) # Equivalently, we could define this function directly instead of using # exec. This version has the advantage of giving the helper function a # more interpettable name. Otherwise, the original function does not # show up at all in many cases, e.g., if it's written in C or if the # dispatcher gets an invalid keyword argument. source = textwrap.dedent(""" @functools.wraps(implementation) def {name}(*args, **kwargs): relevant_args = dispatcher(*args, **kwargs) return implement_array_function( implementation, {name}, relevant_args, args, kwargs) """).format(name=implementation.__name__) source_object = compile( source, filename='<__array_function__ internals>', mode='exec') scope = { 'implementation': implementation, 'dispatcher': dispatcher, 'functools': functools, 'implement_array_function': implement_array_function, } exec(source_object, scope) public_api = scope[implementation.__name__] if module is not None: public_api.__module__ = module return public_api
def decorator(implementation): if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) if module is not None: implementation.__module__ = module return implementation
add_docstring( implement_array_function, """ Implement a function with checks for __array_function__ overrides. All arguments are required, and can only be passed by position. Parameters ---------- implementation : function Function that implements the operation on NumPy array without overrides when called like ``implementation(*args, **kwargs)``. public_api : function Function exposed by NumPy's public API originally called like ``public_api(*args, **kwargs)`` on which arguments are now being checked. relevant_args : iterable Iterable of arguments to check for __array_function__ methods. args : tuple Arbitrary positional arguments originally passed into ``public_api``. kwargs : dict Arbitrary keyword arguments originally passed into ``public_api``. Returns ------- Result from calling ``implementation()`` or an ``__array_function__`` method, as appropriate. Raises ------ TypeError : if no implementation is found. """)
add_docstring( implement_array_function, """ Implement a function with checks for __array_function__ overrides. All arguments are required, and can only be passed by position. Arguments --------- implementation : function Function that implements the operation on NumPy array without overrides when called like ``implementation(*args, **kwargs)``. public_api : function Function exposed by NumPy's public API originally called like ``public_api(*args, **kwargs)`` on which arguments are now being checked. relevant_args : iterable Iterable of arguments to check for __array_function__ methods. args : tuple Arbitrary positional arguments originally passed into ``public_api``. kwargs : dict Arbitrary keyword arguments originally passed into ``public_api``. Returns ------- Result from calling ``implementation()`` or an ``__array_function__`` method, as appropriate. Raises ------ TypeError : if no implementation is found. """)
def decorator(implementation): if module is not None: implementation.__module__ = module if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) return implementation