Skip to content

Include a sequence and combine alternative which is typed #1

Open
@robjhornby

Description

@robjhornby

I am interested in a typed version of parsy and would find it useful, the effort in typed-parsy so far is a nice improvement. I read this blog post on this topic and had an idea for an alternative to seq and combine for the *args synatax (not **kwargs unfortunately). I have something working with Pyright (I haven't tried mypy) - see the linked PR below

By using tuple type unpacking from PEP 646, it's possible to add type information to both of these functions which enable creating a sequence of parsers with a flat tuple result type:

  • A function which joins the results of two parsers into a tuple: Parser[A], Parser[B] -> Parser[Tuple[A, B]]. I've called this join for now. (This one doesn't need tuple type unpacking - it is just the Parser.__and__ function.)
  • A function which takes a tuple result and appends a second parser's result to the end: Parser[Tuple[A, B]], Parser[C] -> Parser[Tuple[A, B, C]]. I've called this append for now.

And it's also possible to create a combine method which expects function whose arguments have the same type as the parser's result tuple. The type signature is like this:

from typing import TypeVar

from typing_extensions import TypeVarTuple, Unpack

OUT2 = TypeVar("OUT2")
OUT_T = TypeVarTuple("OUT_T")

# ... in the Parser class
    def combine(self: Parser[Tuple[Unpack[OUT_T]]], combine_fn: Callable[[Unpack[OUT_T]], OUT2]) -> Parser[OUT2]:
        ...

The benefit is that Pyright will compare the Parser result type with the combine_fn arguments and show an issue when they don't match. It also doesn't need the extra step of indexing tuples in a lambda function as shown in the blog post.

I've made these changes in a fork and they seem to be working nicely with Pyright - it's showing me mismatches between a sequence of parsers' results and a function's arguments with useful messages.

For example, in the screenshot below, the demo function expects its first argument to have a type of str. A parser of type Parser[int, str, bool] can be made with the join and append functions. Then where combine is called, VSCode shows that there's a problem - the parser result type doesn't match demo's parameter type in the first argument.

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions