Skip to content

Commit

Permalink
Fix some issues with mypy
Browse files Browse the repository at this point in the history
Parsita has too much magic to fix them all
  • Loading branch information
drhagen committed May 10, 2023
1 parent de91b9a commit ae01c24
Show file tree
Hide file tree
Showing 18 changed files with 36 additions and 33 deletions.
4 changes: 2 additions & 2 deletions src/parsita/parsers/_alternative.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def __init__(self, parser: Parser[Input, Output], *parsers: Parser[Input, Output
super().__init__()
self.parsers = (parser,) + tuple(parsers)

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
for parser in self.parsers:
status = parser.cached_consume(state, reader)
if isinstance(status, Continue):
Expand Down Expand Up @@ -54,7 +54,7 @@ def __init__(self, parser: Parser[Input, Output], *parsers: Parser[Input, Output
super().__init__()
self.parsers = (parser,) + tuple(parsers)

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
longest_success: Optional[Continue] = None
for parser in self.parsers:
status = parser.cached_consume(state, reader)
Expand Down
2 changes: 1 addition & 1 deletion src/parsita/parsers/_any.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class AnyParser(Generic[Input], Parser[Input, Input]):
def __init__(self):
super().__init__()

def consume(self, state: State, reader: Reader[Input]) -> Optional[Continue[Input, Input]]:
def consume(self, state: State[Input], reader: Reader[Input]) -> Optional[Continue[Input, Input]]:
if reader.finished:
state.register_failure("anything", reader)
return None
Expand Down
10 changes: 5 additions & 5 deletions src/parsita/parsers/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
__all__ = ["Parser", "completely_parse_reader"]

from types import MethodType
from typing import Any, Generic, Optional, Sequence
from typing import Any, Generic, List, Optional, Sequence

from .. import options
from ..state import Continue, Failure, Input, Output, ParseError, Reader, Result, State, Success
Expand Down Expand Up @@ -49,7 +49,7 @@ class Parser(Generic[Input, Output]):
def __init__(self):
self.parse = MethodType(options.parse_method, self)

def cached_consume(self, state: State, reader: Reader[Input]) -> Optional[Continue[Input, Output]]:
def cached_consume(self, state: State[Input], reader: Reader[Input]) -> Optional[Continue[Input, Output]]:
"""Match this parser at the given location.
This is a concrete wrapper around ``consume``. This method implements
Expand Down Expand Up @@ -88,7 +88,7 @@ def cached_consume(self, state: State, reader: Reader[Input]) -> Optional[Contin

return result

def consume(self, state: State, reader: Reader[Input]) -> Optional[Continue[Input, Output]]:
def consume(self, state: State[Input], reader: Reader[Input]) -> Optional[Continue[Input, Output]]:
"""Abstract method for matching this parser at the given location.
This is the central method of every parser combinator.
Expand Down Expand Up @@ -152,7 +152,7 @@ def __or__(self, other) -> Parser:
from ._alternative import AlternativeParser

other = self.handle_other(other)
parsers = []
parsers: List[Parser] = []
if isinstance(self, AlternativeParser) and not self.protected:
parsers.extend(self.parsers)
else:
Expand Down Expand Up @@ -228,7 +228,7 @@ def completely_parse_reader(parser: Parser[Input, Output], reader: Reader[Input]
"""
from ._end_of_source import eof

state = State()
state: State[Input] = State()
status = (parser << eof).cached_consume(state, reader)

if isinstance(status, Continue):
Expand Down
6 changes: 3 additions & 3 deletions src/parsita/parsers/_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __init__(self, parser: Parser[Input, Output], converter: Callable[[Output],
self.parser = parser
self.converter = converter

def consume(self, state: State, reader: Reader[Input]) -> Optional[Continue[Input, Convert]]:
def consume(self, state: State[Input], reader: Reader[Input]) -> Optional[Continue[Input, Convert]]:
status = self.parser.cached_consume(state, reader)

if isinstance(status, Continue):
Expand All @@ -27,12 +27,12 @@ def __repr__(self):


class TransformationParser(Generic[Input, Output, Convert], Parser[Input, Convert]):
def __init__(self, parser: Parser[Input, Output], transformer: Callable[[Output], Parser[Output, Convert]]):
def __init__(self, parser: Parser[Input, Output], transformer: Callable[[Output], Parser[Input, Convert]]):
super().__init__()
self.parser = parser
self.transformer = transformer

def consume(self, state: State, reader: Reader[Input]) -> Optional[Continue[Input, Convert]]:
def consume(self, state: State[Input], reader: Reader[Input]) -> Optional[Continue[Input, Convert]]:
status = self.parser.cached_consume(state, reader)

if isinstance(status, Continue):
Expand Down
2 changes: 1 addition & 1 deletion src/parsita/parsers/_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def __init__(
self.callback = callback
self._parser_string = repr(parser)

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
if self.verbose:
print(f"""Evaluating token {reader.next_token()} using parser {self._parser_string}""")

Expand Down
2 changes: 1 addition & 1 deletion src/parsita/parsers/_end_of_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class EndOfSourceParser(Generic[Input], Parser[Input, None]):
def __init__(self):
super().__init__()

def consume(self, state: State, reader: Reader[Input]) -> Optional[Continue[Input, None]]:
def consume(self, state: State[Input], reader: Reader[Input]) -> Optional[Continue[Input, None]]:
if reader.finished:
return Continue(reader, None)
else:
Expand Down
4 changes: 2 additions & 2 deletions src/parsita/parsers/_literal.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def __init__(self, pattern: Sequence[Input]):
super().__init__()
self.pattern = pattern

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
remainder = reader
for elem in self.pattern:
if remainder.finished:
Expand All @@ -36,7 +36,7 @@ def __init__(self, pattern: str, whitespace: Optional[Parser[str, None]] = None)
self.whitespace = whitespace
self.pattern = pattern

def consume(self, state: State, reader: StringReader):
def consume(self, state: State[str], reader: StringReader):
if self.whitespace is not None:
status = self.whitespace.cached_consume(state, reader)
reader = status.remainder
Expand Down
2 changes: 1 addition & 1 deletion src/parsita/parsers/_optional.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def __init__(self, parser: Parser[Input, Output]):
super().__init__()
self.parser = parser

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
status = self.parser.cached_consume(state, reader)

if isinstance(status, Continue):
Expand Down
2 changes: 1 addition & 1 deletion src/parsita/parsers/_predicate.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def __init__(self, parser: Parser[Input, Output], predicate: Callable[[Output],
self.predicate = predicate
self.description = description

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
remainder = reader
status = self.parser.cached_consume(state, remainder)
if isinstance(status, Continue):
Expand Down
2 changes: 1 addition & 1 deletion src/parsita/parsers/_regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def __init__(self, pattern: str, whitespace: Optional[Parser[str, None]] = None)
self.whitespace = whitespace
self.pattern = re.compile(pattern)

def consume(self, state: State, reader: StringReader):
def consume(self, state: State[str], reader: StringReader):
if self.whitespace is not None:
status = self.whitespace.cached_consume(state, reader)
reader = status.remainder
Expand Down
8 changes: 4 additions & 4 deletions src/parsita/parsers/_repeated.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
__all__ = ["RepeatedOnceParser", "rep1", "RepeatedParser", "rep"]

from typing import Generic, Optional, Sequence, Union
from typing import Generic, List, Optional, Sequence, Union

from ..state import Continue, Input, Output, Reader, RecursionError, State
from ._base import Parser
Expand All @@ -12,7 +12,7 @@ def __init__(self, parser: Parser[Input, Output]):
super().__init__()
self.parser = parser

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
status = self.parser.cached_consume(state, reader)

if status is None:
Expand Down Expand Up @@ -58,8 +58,8 @@ def __init__(self, parser: Parser[Input, Output], *, min: int = 0, max: Optional
self.min = min
self.max = max

def consume(self, state: State, reader: Reader[Input]):
output = []
def consume(self, state: State[Input], reader: Reader[Input]):
output: List[Output] = []
remainder = reader

while self.max is None or len(output) < self.max:
Expand Down
4 changes: 2 additions & 2 deletions src/parsita/parsers/_repeated_seperated.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __init__(
self.min = min
self.max = max

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
status = self.parser.cached_consume(state, reader)

if not isinstance(status, Continue):
Expand Down Expand Up @@ -98,7 +98,7 @@ def __init__(self, parser: Parser[Input, Output], separator: Parser[Input, Any])
self.parser = parser
self.separator = separator

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
status = self.parser.cached_consume(state, reader)

if status is None:
Expand Down
6 changes: 3 additions & 3 deletions src/parsita/parsers/_sequential.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def __init__(self, parser: Parser[Input, Any], *parsers: Parser[Input, Any]):
super().__init__()
self.parsers = (parser,) + tuple(parsers)

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
output = []
remainder = reader

Expand Down Expand Up @@ -39,7 +39,7 @@ def __init__(self, left: Parser[Input, Any], right: Parser[Input, Output]):
self.left = left
self.right = right

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
status = self.left.cached_consume(state, reader)
if isinstance(status, Continue):
return self.right.cached_consume(state, status.remainder)
Expand All @@ -56,7 +56,7 @@ def __init__(self, left: Parser[Input, Output], right: Parser[Input, Any]):
self.left = left
self.right = right

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
status1 = self.left.cached_consume(state, reader)
if isinstance(status1, Continue):
status2 = self.right.cached_consume(state, status1.remainder)
Expand Down
4 changes: 2 additions & 2 deletions src/parsita/parsers/_success.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def __init__(self, value: Output):
super().__init__()
self.value = value

def consume(self, state: State, reader: Reader[Input]) -> Continue[Input, None]:
def consume(self, state: State[Input], reader: Reader[Input]) -> Continue[Input, Output]:
return Continue(reader, self.value)

def __repr__(self):
Expand All @@ -36,7 +36,7 @@ def __init__(self, expected: str):
super().__init__()
self.expected = expected

def consume(self, state: State, reader: Reader[Input]) -> None:
def consume(self, state: State[Input], reader: Reader[Input]) -> None:
state.register_failure(self.expected, reader)
return None

Expand Down
2 changes: 1 addition & 1 deletion src/parsita/parsers/_until.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def __init__(self, parser: Parser[Input, Any]):
super().__init__()
self.parser = parser

def consume(self, state: State, reader: Reader[Input]):
def consume(self, state: State[Input], reader: Reader[Input]):
start_position = reader.position
while True:
status = self.parser.cached_consume(state, reader)
Expand Down
2 changes: 2 additions & 0 deletions src/parsita/state/_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class Reader(Generic[Input]):
source (Sequence[Input]): The full source being read.
"""

# Despite what mypy says, these cannot be converted to properties because
# they will break the dataclass attributes of the subclasses.
first: Input
rest: Reader[Input]
position: int
Expand Down
3 changes: 2 additions & 1 deletion src/parsita/state/_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
# Reexport Returns Result types
Result = result.Result[Output, ParseError]
Success = result.Success
Failure = result.Failure
if TYPE_CHECKING:
# This object fails in isinstance
# Result does too, but that cannot be fixed without breaking eager type annotations
Failure = result.Failure[ParseError]
else:
Failure = result.Failure
4 changes: 2 additions & 2 deletions src/parsita/state/_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
Output = TypeVar("Output")


class State:
class State(Generic[Input]):
def __init__(self):
self.farthest: Optional[Reader[Any]] = None
self.expected: List[str] = []
self.memo: Dict[Tuple[Parser[Any, Any], int], Optional[Continue[Any, Any]]] = {}
self.memo: Dict[Tuple[Parser[Input, Any], int], Optional[Continue[Input, Any]]] = {}

def register_failure(self, expected: str, reader: Reader[Any]):
if self.farthest is None or self.farthest.position < reader.position:
Expand Down

0 comments on commit ae01c24

Please sign in to comment.