Skip to content

Commit 5bc22a4

Browse files
committed
Fix using digit field numbering and types
closes #125
1 parent 1269006 commit 5bc22a4

3 files changed

Lines changed: 43 additions & 18 deletions

File tree

README.rst

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,15 @@ Some simple parse() format string examples:
7878
7979
>>> parse("Bring me a {}", "Bring me a shrubbery")
8080
<Result ('shrubbery',) {}>
81-
>>> r = parse("The {} who say {}", "The knights who say Ni!")
81+
>>> r = parse("The {} who {} {}", "The knights who say Ni!")
8282
>>> print(r)
83-
<Result ('knights', 'Ni!') {}>
83+
<Result ('knights', 'say', 'Ni!') {}>
8484
>>> print(r.fixed)
85-
('knights', 'Ni!')
85+
('knights', 'say', 'Ni!')
86+
>>> print(r[0])
87+
knights
88+
>>> print(r[1:])
89+
('say', 'Ni!')
8690
>>> r = parse("Bring out the holy {item}", "Bring out the holy hand grenade")
8791
>>> print(r)
8892
<Result () {'item': 'hand grenade'}>
@@ -93,8 +97,11 @@ Some simple parse() format string examples:
9397
>>> 'item' in r
9498
True
9599
96-
Note that ``in`` only works if you have named fields. Dotted names and indexes
97-
are possible though the application must make additional sense of the result:
100+
Note that `in` only works if you have named fields.
101+
102+
Dotted names and indexes are possible with some limits. Only word identifiers
103+
are supported (ie. no numeric indexes) and the application must make additional
104+
sense of the result:
98105

99106
.. code-block:: pycon
100107
@@ -377,6 +384,9 @@ the pattern, the actual match represents the shortest successful match for
377384

378385
----
379386

387+
- 1.19.0 Added slice access to fixed results (thanks @jonathangjertsen).
388+
Also corrected matching of *full string* vs. *full line* (thanks @giladreti)
389+
Fix issue with using digit field numbering and types
380390
- 1.18.0 Correct bug in int parsing introduced in 1.16.0 (thanks @maxxk)
381391
- 1.17.0 Make left- and center-aligned search consume up to next space
382392
- 1.16.0 Make compiled parse objects pickleable (thanks @martinResearch)
@@ -453,5 +463,5 @@ the pattern, the actual match represents the shortest successful match for
453463
and removed the restriction on mixing fixed-position and named fields
454464
- 1.0.0 initial release
455465
456-
This code is copyright 2012-2020 Richard Jones <richard@python.org>
466+
This code is copyright 2012-2021 Richard Jones <richard@python.org>
457467
See the end of the source file for the license of use.

parse.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,11 @@
9797
>>> 'item' in r
9898
True
9999
100-
Note that `in` only works if you have named fields. Dotted names and indexes
101-
are possible though the application must make additional sense of the result:
100+
Note that `in` only works if you have named fields.
101+
102+
Dotted names and indexes are possible with some limits. Only word identifiers
103+
are supported (ie. no numeric indexes) and the application must make additional
104+
sense of the result:
102105
103106
.. code-block:: pycon
104107
@@ -381,7 +384,9 @@
381384
382385
----
383386
384-
- 1.19.0 Added slice access to fixed results (thanks @jonathangjertsen)
387+
- 1.19.0 Added slice access to fixed results (thanks @jonathangjertsen).
388+
Also corrected matching of *full string* vs. *full line* (thanks @giladreti)
389+
Fix issue with using digit field numbering and types
385390
- 1.18.0 Correct bug in int parsing introduced in 1.16.0 (thanks @maxxk)
386391
- 1.17.0 Make left- and center-aligned search consume up to next space
387392
- 1.16.0 Make compiled parse objects pickleable (thanks @martinResearch)
@@ -458,13 +463,13 @@
458463
and removed the restriction on mixing fixed-position and named fields
459464
- 1.0.0 initial release
460465
461-
This code is copyright 2012-2020 Richard Jones <richard@python.org>
466+
This code is copyright 2012-2021 Richard Jones <richard@python.org>
462467
See the end of the source file for the license of use.
463468
'''
464469

465470
from __future__ import absolute_import
466471

467-
__version__ = '1.18.0'
472+
__version__ = '1.19.0'
468473

469474
# yes, I now have two problems
470475
import re
@@ -1032,11 +1037,17 @@ def _handle_field(self, field):
10321037
# now figure whether this is an anonymous or named field, and whether
10331038
# there's any format specification
10341039
format = ''
1035-
if field and field[0].isalpha():
1036-
if ':' in field:
1037-
name, format = field.split(':')
1038-
else:
1039-
name = field
1040+
1041+
if ':' in field:
1042+
name, format = field.split(':')
1043+
else:
1044+
name = field
1045+
1046+
# This *should* be more flexible, but parsing complicated structures
1047+
# out of the string is hard (and not necessarily useful) ... and I'm
1048+
# being lazy. So for now `identifier` is "anything starting with a
1049+
# letter" and digit args don't get attribute or element stuff.
1050+
if name and name[0].isalpha():
10401051
if name in self._name_to_group_map:
10411052
if self._name_types[name] != format:
10421053
raise RepeatedNameError(
@@ -1056,8 +1067,6 @@ def _handle_field(self, field):
10561067
else:
10571068
self._fixed_fields.append(self._group_index)
10581069
wrap = r'(%s)'
1059-
if ':' in field:
1060-
format = field[1:]
10611070
group = self._group_index
10621071

10631072
# simplest case: no type specifier ({} or {name})

test_parse.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ def test_named_typed(self):
3737
self._test_expression('{name:w}', r'(?P<name>\w+)')
3838
self._test_expression('{name:w} {other:w}', r'(?P<name>\w+) (?P<other>\w+)')
3939

40+
def test_numbered(self):
41+
self._test_expression('{0}', r'(.+?)')
42+
self._test_expression('{0} {1}', r'(.+?) (.+?)')
43+
self._test_expression('{0:f} {1:f}', r'([-+ ]?\d*\.\d+) ([-+ ]?\d*\.\d+)')
44+
4045
def test_bird(self):
4146
# skip some trailing whitespace
4247
self._test_expression('{:>}', r' *(.+?)')
@@ -1076,6 +1081,7 @@ def test_int_convert_stateless_base(self):
10761081
self.assertEqual(parser.parse("1234")[0], 1234)
10771082
self.assertEqual(parser.parse("0b1011")[0], 0b1011)
10781083

1084+
10791085
if __name__ == '__main__':
10801086
unittest.main()
10811087

0 commit comments

Comments
 (0)