On Tue, Aug 29, 2017 at 1:06 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
On 29 August 2017 at 18:58, Blaine Rogers <blaine.w.rogers@gmail.com> wrote:
> The current syntax for Callable types is unwieldy, particularly when
> extended to include varargs and keyword args as in
> http://mypy.readthedocs.io/en/latest/kinds_of_types.html#extended-callable-types.
> Why not introduce a signature literal?

While a more concise spelling for that is desirable, it doesn't need
to be a literal, as it can be handled by updating the Callable item
lookup to accept a string literal that static type checkers know how
to parse.

The standard library already contains a runtime introspection variant
of this to pass function signature details from Argument Clinic up to
inspect.Signature as __text_signature__ attributes:
https://github.com/python/cpython/blob/master/Lib/inspect.py#L1938

The main reason "create signature object from text string" isn't a
public API yet is because it includes support for positional-only and
variable signatures that aren't supported by pure Python function
definitions (while https://www.python.org/dev/peps/pep-0457/ covers
the details of how that works, my recollection is that Guido was wary
of accepting an approved syntax in the absence of actual syntactic
support for them in function definitions)


​How about:

    def func(a: int​, b: str) -> float: ...

? ;-)


​—Koos
    from inspect import Signature, _signature_fromstr

    def str_signature(sig):
        parsed_sig = _signature_fromstr(Signature, (lambda: None), sig)
        for param in parsed_sig.parameters.values(): print("{}:
{}".format(param, param.kind.name))

    >>> str_signature("(a, b, /, c, d)")
    a: POSITIONAL_ONLY
    b: POSITIONAL_ONLY
    c: POSITIONAL_OR_KEYWORD
    d: POSITIONAL_OR_KEYWORD

Using PEP 457 syntax and a string literal, the MyPy extended callable
syntax would look like:

    func(__a: int,  # This convention is for nameless arguments
             b: int,
             c: int = 0,
             *args: int,
             d: int,
             e: int = 0,
             **kwargs: int) -> int:
        ...

    F = Callable[
        """(
            a: int, /,
            b: int, c: int = 0, *args: int,
            d: int, e: int = 0, **kwargs: int
        )""",
        int]

Ideally, the runtime implementation of that would *skip* parsing the
signature, and instead just keep the string around for on-demand
parsing.

Cheers,
Nick.





--
+ Koos Zevenhoven + http://twitter.com/k7hoven +