Skip to content

Commit

Permalink
test: stream api
Browse files Browse the repository at this point in the history
  • Loading branch information
bdura committed Apr 19, 2024
1 parent 476820e commit c2b365b
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 184 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

# Python
__pycache__
.hypothesis
.venv

# Coverage
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ Persil is a pure-python parsing library that draws much (most, let's be honest)
of its inspiration from the excellent [Parsy](https://github.com/python-parsy/parsy) library.

Hence the name, "Persil" ([pɛʁ.sil] or [pɛʁ.si]), the French word for parsley
-a most questionable pun on `Parsy -> Parsley -> Persil`,
in case anyone missed it.
-a most questionable pun on `Parsy -> Parsley -> Persil`, in case anyone missed it.

Like Parsy, Persil is a _"monadic parser combinator library for LL(infinity) grammars"_.
As a rough approximation, you can think of Persil as a typed "fork" of Parsy.
Expand Down
4 changes: 3 additions & 1 deletion persil/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@


class SoftError(Exception):
inner: Err
def __init__(self, inner: Err) -> None:
self.inner = inner
super().__init__()


class Stream(Generic[In]):
Expand Down
186 changes: 64 additions & 122 deletions poetry.lock

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,19 @@ pre-commit = "^3.7.0"
mypy = "^1.9.0"
pytest = "^8.1.1"
pytest-cov = "^5.0.0"
pydantic = "^2.6.4"


[tool.poetry.group.docs.dependencies]
mkdocs-material = "^9.5.18"
mkdocstrings = {extras = ["python"], version = "^0.24.3"}
mike = "^2.0.0"


[tool.poetry.group.tests.dependencies]
pytest = "^8.1.1"
pytest-cov = "^5.0.0"
hypothesis = "^6.100.1"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Expand Down
43 changes: 21 additions & 22 deletions tests/test_from_stream.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
import pytest
from pydantic import BaseModel

from persil import regex
from persil.stream import Stream, from_stream
from datetime import datetime

from hypothesis import given
from hypothesis import strategies as st

class Flight(BaseModel):
carrier: str
flight_number: int

from persil import regex, string
from persil.stream import Stream, from_stream

@from_stream("Flight parser")
def flight_parser(stream: Stream[str]) -> Flight:
carrier = stream.apply(regex(r"[A-Z]{2}"))
flight_number = stream.apply(regex(r"\d{2,4}").map(int))
year_parser = regex(r"\d{4}").map(int)
month_parser = regex(r"(?:0\d|1[012])").map(int)
day_parser = regex(r"(?:[012]\d|3[01])").map(int)

return Flight(carrier=carrier, flight_number=flight_number)

@from_stream
def datetime_parser(stream: Stream[str]) -> datetime:
year = stream.apply(year_parser)
stream.apply(string("-"))
month = stream.apply(month_parser)
stream.apply(string("-"))
day = stream.apply(day_parser)

EXAMPLES = [
("AF071", Flight(carrier="AF", flight_number=71)),
("LY180", Flight(carrier="LY", flight_number=180)),
]
return datetime(year, month, day)


@pytest.mark.parametrize("message,expected", EXAMPLES)
def test_generate(message: str, expected: Flight):
flight = flight_parser.parse(message)
assert flight == expected
@given(st.datetimes())
def test_generate(dt: datetime):
dt = datetime(dt.year, dt.month, dt.day)
text = dt.strftime("%Y-%m-%d")
assert datetime_parser.parse(text) == dt
36 changes: 0 additions & 36 deletions tests/test_generate.py

This file was deleted.

0 comments on commit c2b365b

Please sign in to comment.