Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convenience factories for the Ingress class #11

Open
thorwhalen opened this issue Nov 2, 2021 · 0 comments
Open

Convenience factories for the Ingress class #11

thorwhalen opened this issue Nov 2, 2021 · 0 comments
Assignees
Labels
enhancement New feature or request

Comments

@thorwhalen
Copy link
Member

thorwhalen commented Nov 2, 2021

The docs of Ingress mention:

I quote:

  • inner_sig: Signature of the inner function the ingress is for.
    The function itself can be given and the signature will be extracted.
  • kwargs_trans: A dict-to-dict transformation of the outer kwargs to
    the kwargs that should be input to the inner function.
  • outer_sig: The outer signature. The signature the ingress function
    (there for the wrapped function) will have. Also serves to convert input
    (args, kwargs) to the kwargs that will be given to kwargs_trans.

When making an Ingress function directly, one must take care that
inner_sig, kwargs_trans and outer_sig are aligned.

Namely, 'kwargs_trans' must be able to handle outputs of
outer_sig.kwargs_from_args_and_kwargs and itself output kwargs that
can be handled by inner_sig.args_and_kwargs_from_kwargs.

End quote.

We need to provide a few convenience factories (perhaps as classmethods) to make the specification of Ingress arguments less fiddly.

Some ideas follow

Specifying the outer_sig and kwargs_trans in one whoosh

def kw_ingress(a: int, b=1, * c: float = 2.7):
    return {'ab': a * b, 'zoo': c}

Ingress.from_kwargs_ingress(inner_sig, kw_ingress)

Specifying the outer_sig from a transformation of the inner_sig

What was done in InnerMapIngress, messily.

inner_sig.modified is key here, but there may be some name mapping involved as well

# Say you want to transform
# inner_sig: (w, /, x: float = 1, y=2, *, z: int = 3)
# into the outer sig (and transformation) equivalent to:
# def directly_defined_ingress(w, x: int, you: int=2, z = 10):
#     return (w,), dict(x=x, y=you, z=z)

outer_sig = transform_sig(inner_sig, 
    ...     w=dict(kind=PK),
    ...     # change annotation of x from float to int and remove default
    ...     x=dict(annotation=int, default=empty),
    ...     # rename y to you and add annotation int:
    ...     y=dict(name='you', annotation=int),
    ...     # change kind to PK, default to 10, and remove annotation:
    ...     z=dict(kind=PK, default=10, annotation=empty),
)

# but it's not all about `outer_sig`, need the mapping too, to include with the kwargs_trans!

Specifying the inner_sig from a transformation of the outer_sig

Similar to the inverse

Specifying kwargs_trans from outer to inner

See IterativeDictProcessing

kwargs_trans = mk_kwargs_trans_from_outer(
    a = lambda x, y: x + y,  # add kwargs['x'] and kwargs['y'], a many-to-one case
    b = 'z'  # equivalent to lambda z: z  # the value of `z`; this is just renaming
    c = lambda u: u % 3,  # with the definition of d, it's a one-to-many case
    d = lambda u: u // 3
)

Specifying kwargs_trans from inner to outer

When running the wrapped function, the flow goes from outer inputs, the transformation for the inner function.
Therefore, expressing the outer as a function of the inner may seem awkward.
yet, in some contexts it's an easier expression of what is desired.

For instance ou may want to map internal names (or annotations, or defaults) in such a way that the resultant
interface makes sense for the wrapper's environment.

In this case, we need a mechanism to explicitly or implicitly define outer-to-inner functions according to properties of the inner. If the outer-to-inner mapping is invertible, this is straightforward, but could be complicated if not.

┆Issue is synchronized with this Asana task by Unito

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants