def test_spans(self): # test the string sections our fields come from string = 'hello world' r = parse.parse('hello {}', string) self.assertEqual(r.spans, {0: (6, 11)}) start, end = r.spans[0] self.assertEqual(string[start:end], r.fixed[0]) string = 'hello world' r = parse.parse('hello {:>}', string) self.assertEqual(r.spans, {0: (10, 15)}) start, end = r.spans[0] self.assertEqual(string[start:end], r.fixed[0]) string = 'hello 0x12 world' r = parse.parse('hello {val:x} world', string) self.assertEqual(r.spans, {'val': (6, 10)}) start, end = r.spans['val'] self.assertEqual(string[start:end], '0x%x' % r.named['val']) string = 'hello world and other beings' r = parse.parse('hello {} {name} {} {spam}', string) self.assertEqual(r.spans, { 0: (6, 11), 'name': (12, 15), 1: (16, 21), 'spam': (22, 28) })
def test_dotted_type_conversion_pull_8(self): # test pull request 8 which fixes type conversion related to dotted # names being applied correctly r = parse.parse('{a.b:d}', '1') self.assertEqual(r['a.b'], 1) r = parse.parse('{a_b:w} {a.b:d}', '1 2') self.assertEqual(r['a_b'], '1') self.assertEqual(r['a.b'], 2)
def test_regular_expression(self): # match an actual regular expression s = r'^(hello\s[wW]{}!+.*)$' e = s.replace('{}', 'orld') r = parse.parse(s, e) self.assertEqual(r.fixed, ('orld',)) e = s.replace('{}', '.*?') r = parse.parse(s, e) self.assertEqual(r.fixed, ('.*?',))
def test_named_aligned_typed(self): # pull a named, typed values out of string r = parse.parse('hello {number:<d} {things}', 'hello 12 people') self.assertEqual(r.named, dict(number=12, things='people')) r = parse.parse('hello {number:>d} {things}', 'hello 12 people') self.assertEqual(r.named, dict(number=12, things='people')) r = parse.parse('hello {number:^d} {things}', 'hello 12 people') self.assertEqual(r.named, dict(number=12, things='people'))
def test_regular_expression(self): # match an actual regular expression s = r'^(hello\s[wW]{}!+.*)$' e = s.replace('{}', 'orld') r = parse.parse(s, e) self.assertEqual(r.fixed, ('orld', )) e = s.replace('{}', '.*?') r = parse.parse(s, e) self.assertEqual(r.fixed, ('.*?', ))
def test_custom_type(self): # use a custom type r = parse.parse('{:shouty} {:spam}', 'hello world', dict(shouty=lambda s: s.upper(), spam=lambda s: ''.join(reversed(s)))) self.assertEqual(r.fixed, ('HELLO', 'dlrow')) r = parse.parse('{:d}', '12', dict(d=lambda s: int(s) * 2)) self.assertEqual(r.fixed, (24,)) r = parse.parse('{:d}', '12') self.assertEqual(r.fixed, (12,))
def test_custom_type(self): # use a custom type r = parse.parse( '{:shouty} {:spam}', 'hello world', dict(shouty=lambda s: s.upper(), spam=lambda s: ''.join(reversed(s)))) self.assertEqual(r.fixed, ('HELLO', 'dlrow')) r = parse.parse('{:d}', '12', dict(d=lambda s: int(s) * 2)) self.assertEqual(r.fixed, (24, )) r = parse.parse('{:d}', '12') self.assertEqual(r.fixed, (12, ))
def test_named_date_issue7(self): r = parse.parse('on {date:ti}', 'on 2012-09-17') self.assertEqual(r['date'], datetime(2012, 9, 17, 0, 0, 0)) # fix introduced regressions r = parse.parse('a {:ti} b', 'a 1997-07-16T19:20 b') self.assertEqual(r[0], datetime(1997, 7, 16, 19, 20, 0)) r = parse.parse('a {:ti} b', 'a 1997-07-16T19:20Z b') utc = parse.FixedTzOffset(0, 'UTC') self.assertEqual(r[0], datetime(1997, 7, 16, 19, 20, tzinfo=utc)) r = parse.parse('a {date:ti} b', 'a 1997-07-16T19:20Z b') self.assertEqual(r['date'], datetime(1997, 7, 16, 19, 20, tzinfo=utc))
def test_dot_separated_fields_name_collisions(self): # this should just work and provide the named value res = parse.parse('{a_.b}_{a__b}_{a._b}_{a___b}', 'a_b_c_d') assert res.named['a_.b'] == 'a' assert res.named['a__b'] == 'b' assert res.named['a._b'] == 'c' assert res.named['a___b'] == 'd'
def test_mixed_types(self): # stress-test: pull one of everything out of a string r = parse.parse( ''' letters: {:w} non-letters: {:W} whitespace: "{:s}" non-whitespace: \t{:S}\n digits: {:d} {:d} non-digits: {:D} numbers with thousands: {:n} fixed-point: {:f} floating-point: {:e} general numbers: {:g} {:g} binary: {:b} octal: {:o} hex: {:x} ISO 8601 e.g. {:ti} RFC2822 e.g. {:te} Global e.g. {:tg} US e.g. {:ta} ctime() e.g. {:tc} HTTP e.g. {:th} time: {:tt} final value: {} ''', ''' letters: abcdef_GHIJLK non-letters: !@#%$ *^% whitespace: " \t\n" non-whitespace: \tabc\n digits: 12345 0b1011011 non-digits: abcdef numbers with thousands: 1,000 fixed-point: 100.2345 floating-point: 1.1e-10 general numbers: 1 1.1 binary: 0b1000 octal: 0o1000 hex: 0x1000 ISO 8601 e.g. 1972-01-20T10:21:36Z RFC2822 e.g. Mon, 20 Jan 1972 10:21:36 +1000 Global e.g. 20/1/1972 10:21:36 AM +1:00 US e.g. 1/20/1972 10:21:36 PM +10:30 ctime() e.g. Sun Sep 16 01:03:52 1973 HTTP e.g. 21/Nov/2011:00:07:11 +0000 time: 10:21:36 PM -5:30 final value: spam ''') self.assertNotEqual(r, None) self.assertEqual(r.fixed[22], 'spam')
def test_mixed_types(self): # stress-test: pull one of everything out of a string r = parse.parse(''' letters: {:w} non-letters: {:W} whitespace: "{:s}" non-whitespace: \t{:S}\n digits: {:d} {:d} non-digits: {:D} numbers with thousands: {:n} fixed-point: {:f} floating-point: {:e} general numbers: {:g} {:g} binary: {:b} octal: {:o} hex: {:x} ISO 8601 e.g. {:ti} RFC2822 e.g. {:te} Global e.g. {:tg} US e.g. {:ta} ctime() e.g. {:tc} HTTP e.g. {:th} time: {:tt} final value: {} ''', ''' letters: abcdef_GHIJLK non-letters: !@#%$ *^% whitespace: " \t\n" non-whitespace: \tabc\n digits: 12345 0b1011011 non-digits: abcdef numbers with thousands: 1,000 fixed-point: 100.2345 floating-point: 1.1e-10 general numbers: 1 1.1 binary: 0b1000 octal: 0o1000 hex: 0x1000 ISO 8601 e.g. 1972-01-20T10:21:36Z RFC2822 e.g. Mon, 20 Jan 1972 10:21:36 +1000 Global e.g. 20/1/1972 10:21:36 AM +1:00 US e.g. 1/20/1972 10:21:36 PM +10:30 ctime() e.g. Sun Sep 16 01:03:52 1973 HTTP e.g. 21/Nov/2011:00:07:11 +0000 time: 10:21:36 PM -5:30 final value: spam ''') self.assertNotEqual(r, None) self.assertEqual(r.fixed[22], 'spam')
def test_mixed_type_variant(self): r = parse.parse( ''' letters: {:w} non-letters: {:W} whitespace: "{:s}" non-whitespace: \t{:S}\n digits: {:d} non-digits: {:D} numbers with thousands: {:n} fixed-point: {:f} floating-point: {:e} general numbers: {:g} {:g} binary: {:b} octal: {:o} hex: {:x} ISO 8601 e.g. {:ti} RFC2822 e.g. {:te} Global e.g. {:tg} US e.g. {:ta} ctime() e.g. {:tc} HTTP e.g. {:th} time: {:tt} final value: {} ''', ''' letters: abcdef_GHIJLK non-letters: !@#%$ *^% whitespace: " \t\n" non-whitespace: \tabc\n digits: 0xabcdef non-digits: abcdef numbers with thousands: 1.000.000 fixed-point: 0.00001 floating-point: NAN general numbers: 1.1e10 nan binary: 0B1000 octal: 0O1000 hex: 0X1000 ISO 8601 e.g. 1972-01-20T10:21:36Z RFC2822 e.g. Mon, 20 Jan 1972 10:21:36 +1000 Global e.g. 20/1/1972 10:21:36 AM +1:00 US e.g. 1/20/1972 10:21:36 PM +10:30 ctime() e.g. Sun Sep 16 01:03:52 1973 HTTP e.g. 21/Nov/2011:00:07:11 +0000 time: 10:21:36 PM -5:30 final value: spam ''') self.assertNotEqual(r, None) self.assertEqual(r.fixed[21], 'spam')
def test_mixed_type_variant(self): r = parse.parse(''' letters: {:w} non-letters: {:W} whitespace: "{:s}" non-whitespace: \t{:S}\n digits: {:d} non-digits: {:D} numbers with thousands: {:n} fixed-point: {:f} floating-point: {:e} general numbers: {:g} {:g} binary: {:b} octal: {:o} hex: {:x} ISO 8601 e.g. {:ti} RFC2822 e.g. {:te} Global e.g. {:tg} US e.g. {:ta} ctime() e.g. {:tc} HTTP e.g. {:th} time: {:tt} final value: {} ''', ''' letters: abcdef_GHIJLK non-letters: !@#%$ *^% whitespace: " \t\n" non-whitespace: \tabc\n digits: 0xabcdef non-digits: abcdef numbers with thousands: 1.000.000 fixed-point: 0.00001 floating-point: NAN general numbers: 1.1e10 nan binary: 0B1000 octal: 0O1000 hex: 0X1000 ISO 8601 e.g. 1972-01-20T10:21:36Z RFC2822 e.g. Mon, 20 Jan 1972 10:21:36 +1000 Global e.g. 20/1/1972 10:21:36 AM +1:00 US e.g. 1/20/1972 10:21:36 PM +10:30 ctime() e.g. Sun Sep 16 01:03:52 1973 HTTP e.g. 21/Nov/2011:00:07:11 +0000 time: 10:21:36 PM -5:30 final value: spam ''') self.assertNotEqual(r, None) self.assertEqual(r.fixed[21], 'spam')
def test_spans(self): # test the string sections our fields come from string = 'hello world' r = parse.parse('hello {}', string) self.assertEqual(r.spans, {0: (6, 11)}) start, end = r.spans[0] self.assertEqual(string[start:end], r.fixed[0]) string = 'hello world' r = parse.parse('hello {:>}', string) self.assertEqual(r.spans, {0: (10, 15)}) start, end = r.spans[0] self.assertEqual(string[start:end], r.fixed[0]) string = 'hello 0x12 world' r = parse.parse('hello {val:x} world', string) self.assertEqual(r.spans, {'val': (6, 10)}) start, end = r.spans['val'] self.assertEqual(string[start:end], '0x%x' % r.named['val']) string = 'hello world and other beings' r = parse.parse('hello {} {name} {} {spam}', string) self.assertEqual(r.spans, {0: (6, 11), 'name': (12, 15), 1: (16, 21), 'spam': (22, 28)})
def test_datetime_group_count(self): # test we increment the group count correctly for datetimes r = parse.parse('{:ti} {}', '1972-01-01 spam') self.assertEqual(r.fixed[1], 'spam') r = parse.parse('{:tg} {}', '1-1-1972 spam') self.assertEqual(r.fixed[1], 'spam') r = parse.parse('{:ta} {}', '1-1-1972 spam') self.assertEqual(r.fixed[1], 'spam') r = parse.parse('{:th} {}', '21/Nov/2011:10:21:36 +1000 spam') self.assertEqual(r.fixed[1], 'spam') r = parse.parse('{:te} {}', '21 Nov 2011 10:21:36 +1000 spam') self.assertEqual(r.fixed[1], 'spam') r = parse.parse('{:tc} {}', 'Mon Nov 21 10:21:36 2011 spam') self.assertEqual(r.fixed[1], 'spam') r = parse.parse('{:tt} {}', '10:21 spam') self.assertEqual(r.fixed[1], 'spam')
def test_multiline(self): r = parse.parse('hello\n{}\nworld', 'hello\nthere\nworld') self.assertEqual(r.fixed[0], 'there')
def test_mixed(self): # pull a fixed and named values out of string r = parse.parse('hello {} {name} {} {spam}', 'hello world and other beings') self.assertEqual(r.fixed, ('world', 'other')) self.assertEqual(r.named, dict(name='and', spam='beings'))
def test_named_repeated_fail_value(self): # test repeated name fails if value mismatches r = parse.parse('{n} {n}', 'x y') self.assertEqual(r, None)
def test_named_repeated(self): # test a name may be repeated r = parse.parse('{n} {n}', 'x x') self.assertEqual(r.named, {'n': 'x'})
def test_typed_fail(self): # pull a named, typed values out of string self.assertEqual(parse.parse('hello {:d} {:w}', 'hello people 12'), None)
def test_typed(self): # pull a named, typed values out of string r = parse.parse('hello {:d} {:w}', 'hello 12 people') self.assertEqual(r.fixed, (12, 'people')) r = parse.parse('hello {:w} {:w}', 'hello 12 people') self.assertEqual(r.fixed, ('12', 'people'))
def test_right(self): # pull right-aligned text out of string r = parse.parse('hello {:>}', 'hello world') self.assertEqual(r.fixed, ('world', ))
def n(fmt, s, e): if parse.parse(fmt, s) is not None: self.fail('%r matched %r' % (fmt, s))
def test_two_datetimes(self): r = parse.parse('a {:ti} {:ti} b', 'a 1997-07-16 2012-08-01 b') self.assertEqual(len(r.fixed), 2) self.assertEqual(r[0], datetime(1997, 7, 16)) self.assertEqual(r[1], datetime(2012, 8, 1))
def test_named(self): # pull a named value out of string r = parse.parse('hello {name}', 'hello world') self.assertEqual(r.named, {'name': 'world'})
def test_pm_overflow_issue16(self): r = parse.parse('Meet at {:tg}', 'Meet at 1/2/2011 12:45 PM') self.assertEqual(r[0], datetime(2011, 2, 2, 0, 45))
def test_center(self): # pull center-aligned text out of string r = parse.parse('hello {:^} world', 'hello there world') self.assertEqual(r.fixed, ('there', ))
def test_dot_separated_fields(self): # this should just work and provide the named value res = parse.parse('{hello.world}_{jojo.foo.baz}_{simple}', 'a_b_c') assert res.named['hello.world'] == 'a' assert res.named['jojo.foo.baz'] == 'b' assert res.named['simple'] == 'c'
def test_nothing(self): # do no actual parsing r = parse.parse('{{hello}}', '{hello}') self.assertEqual(r.fixed, ()) self.assertEqual(r.named, {})
def test_named_repeated_type(self): # test a name may be repeated with type conversion r = parse.parse('{n:d} {n:d}', '1 1') self.assertEqual(r.named, {'n': 1})
def test_named_repeated_type_fail_value(self): # test repeated name with type conversion fails if value mismatches r = parse.parse('{n:d} {n:d}', '1 2') self.assertEqual(r, None)
def test_left(self): # pull left-aligned text out of string r = parse.parse('{:<} world', 'hello world') self.assertEqual(r.fixed, ('hello', ))
def test_question_mark(self): # issue9: make sure a ? in the parse string is handled correctly r = parse.parse('"{}"?', '"teststr"?') self.assertEqual(r[0], 'teststr')
def test_pipe(self): # issue22: make sure a | in the parse string is handled correctly r = parse.parse('| {}', '| teststr') self.assertEqual(r[0], 'teststr')
def test_fixed(self): # pull a fixed value out of string r = parse.parse('hello {}', 'hello world') self.assertEqual(r.fixed, ('world', ))
def test_no_match(self): # string does not match format self.assertEqual(parse.parse('{{hello}}', 'hello'), None)