Skip to content

Commit

Permalink
Allow specifying a default value to optional()
Browse files Browse the repository at this point in the history
  • Loading branch information
unode committed Sep 6, 2022
1 parent d73aada commit cc5a63f
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 5 deletions.
1 change: 1 addition & 0 deletions docs/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ History and release notes

* Dropped support for Python < 3.6
* Added :meth:`Parser.until`. Thanks `@mcdeoliveira <https://github.com/mcdeoliveira>`_!
* `Parser.optional` now supports an optional default argument to be returned instead of ``None``.

1.4.0 - 2021-11-15
------------------
Expand Down
7 changes: 5 additions & 2 deletions docs/ref/methods_and_combinators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,20 @@ can be used and manipulated as below.
.. versionadded:: 2.0

.. method:: optional()
.. method:: optional(default=None)

Returns a parser that expects the initial parser zero or once, and maps
the result to ``None`` in the case of no match.
the result to a given default value in the case of no match. If no default
value is given, ``None`` is used.

.. code:: python
>>> string('A').optional().parse('A')
'A'
>>> string('A').optional().parse('')
None
>>> string('A').optional('Oops').parse('')
'Oops'
.. method:: map(fn)

Expand Down
3 changes: 2 additions & 1 deletion docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@ failing the whole parse.
multiples of the parser - including :meth:`Parser.many`, :meth:`Parser.times`,
:meth:`Parser.at_most` and :meth:`Parser.at_least`. There is also
:meth:`Parser.optional` which allows matching zero times (in which case the
parser will return ``None``), or exactly once - just what we need in this case.
parser will return the default value specified or ``None`` otherwise),
or exactly once - just what we need in this case.

We also need to do checking on the month and the day. We’ll take a shortcut and
use the built-in ``datetime.date`` class to do the validation for us. However,
Expand Down
4 changes: 2 additions & 2 deletions src/parsy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ def at_most(self, n):
def at_least(self, n):
return self.times(n) + self.many()

def optional(self):
return self.times(0, 1).map(lambda v: v[0] if v else None)
def optional(self, default=None):
return self.times(0, 1).map(lambda v: v[0] if v else default)

def until(self, other, min=0, max=float("inf"), consume_other=False):
@Parser
Expand Down
3 changes: 3 additions & 0 deletions tests/test_parsy.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,9 @@ def test_optional(self):
p = string("a").optional()
self.assertEqual(p.parse("a"), "a")
self.assertEqual(p.parse(""), None)
p = string("a").optional("b")
self.assertEqual(p.parse("a"), "a")
self.assertEqual(p.parse(""), "b")

def test_sep_by(self):
digit_list = digit.map(int).sep_by(string(","))
Expand Down

0 comments on commit cc5a63f

Please sign in to comment.