From 9f35109ed5cf2b36aa6640c65cff72caf5b2e018 Mon Sep 17 00:00:00 2001 From: Wil Cooley Date: Tue, 20 Sep 2016 15:57:30 -0700 Subject: [PATCH 1/3] Add test for get_format_str w/tuples and lists --- tests/test_formatutils.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_formatutils.py b/tests/test_formatutils.py index ab7bb980..2b4a9f9a 100644 --- a/tests/test_formatutils.py +++ b/tests/test_formatutils.py @@ -3,6 +3,7 @@ import re from collections import namedtuple +import pytest from boltons.formatutils import (get_format_args, split_format_str, tokenize_format_str, @@ -48,6 +49,18 @@ def test_get_fstr_args(): return results +@pytest.mark.parametrize(('sample', 'expected'), zip(_TEST_TMPLS, [ + ([], [('hello', str)]), + ([], [('hello', str)]), + ([], [('hello', str), ('width', str)]), + ([], [('hello', str), ('fchar', str), ('width', str)]), + ([(0, str), (1, int), (2, float)], []), + # example 6 is skipped +])) +def test_get_format_args(sample, expected): + assert get_format_args(sample) == expected + + def test_split_fstr(): results = [] for t in _TEST_TMPLS: From c3e52e3920c75427e3137f687518f54b51489fae Mon Sep 17 00:00:00 2001 From: Wil Cooley Date: Tue, 20 Sep 2016 16:27:29 -0700 Subject: [PATCH 2/3] Return namedtuples for get_format_args The nested tuple/list structures that are returned by `get_format_args` are fairly cumbersome; returning data `namedtuple` makes accessing the data much cleaner. --- boltons/formatutils.py | 11 ++++++++--- tests/test_formatutils.py | 27 ++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/boltons/formatutils.py b/boltons/formatutils.py index 74b86321..504c026d 100644 --- a/boltons/formatutils.py +++ b/boltons/formatutils.py @@ -41,6 +41,7 @@ import re from string import Formatter +from .namedutils import namedtuple __all__ = ['DeferredValue', 'get_format_args', 'tokenize_format_str', 'construct_format_field_str', 'infer_positional_format_args', @@ -117,6 +118,10 @@ def infer_positional_format_args(fstr): [(x, float) for x in _FLOATCHARS]) _TYPE_MAP['s'] = str +FormatArgs = namedtuple('FormatArgs', ('positional', 'named')) +PositionalFormatArg = namedtuple('PositionalFormatArg', ('index', 'type')) +NamedFormatArg = namedtuple('NamedFormatArg', ('key', 'type')) + def get_format_args(fstr): """ @@ -142,9 +147,9 @@ def _add_arg(argname, type_char='s'): _dedup.add(argname) argtype = _TYPE_MAP.get(type_char, str) # TODO: unicode try: - fargs.append((int(argname), argtype)) + fargs.append(PositionalFormatArg(int(argname), argtype)) except ValueError: - fkwargs.append((argname, argtype)) + fkwargs.append(NamedFormatArg(argname, argtype)) for lit, fname, fspec, conv in formatter.parse(fstr): if fname is not None: @@ -162,7 +167,7 @@ def _add_arg(argname, type_char='s'): # TODO: positional and anon args not allowed here. if subfname is not None: _add_arg(subfname) - return fargs, fkwargs + return FormatArgs(fargs, fkwargs) def tokenize_format_str(fstr, resolve_pos=True): diff --git a/tests/test_formatutils.py b/tests/test_formatutils.py index 2b4a9f9a..283c2191 100644 --- a/tests/test_formatutils.py +++ b/tests/test_formatutils.py @@ -7,7 +7,10 @@ from boltons.formatutils import (get_format_args, split_format_str, tokenize_format_str, - infer_positional_format_args) + infer_positional_format_args, + FormatArgs, + NamedFormatArg, + PositionalFormatArg) PFAT = namedtuple("PositionalFormatArgTest", "fstr arg_vals res") @@ -58,9 +61,31 @@ def test_get_fstr_args(): # example 6 is skipped ])) def test_get_format_args(sample, expected): + """Test `get_format_args` result as tuples.""" assert get_format_args(sample) == expected +@pytest.mark.parametrize(('sample', 'expected'), zip(_TEST_TMPLS, [ + FormatArgs([], [NamedFormatArg('hello', str)]), + FormatArgs([], [NamedFormatArg('hello', str)]), + FormatArgs([], [NamedFormatArg('hello', str), + NamedFormatArg('width', str)]), + FormatArgs([], [NamedFormatArg('hello', str), + NamedFormatArg('fchar', str), + NamedFormatArg('width', str)]), + FormatArgs([PositionalFormatArg(0, str), + PositionalFormatArg(1, int), + PositionalFormatArg(2, float)], []), + # example 6 is skipped +])) +def test_get_format_args_namedtuples(sample, expected): + """Test `get_format_args` result as `namedtuples`.""" + result = get_format_args(sample) + assert result == expected + assert result.positional == expected.positional + assert result.named == expected.named + + def test_split_fstr(): results = [] for t in _TEST_TMPLS: From 8fbd39d1993ee9888252d5610d95a3abe9094e3c Mon Sep 17 00:00:00 2001 From: Wil Cooley Date: Wed, 21 Sep 2016 09:06:11 -0700 Subject: [PATCH 3/3] Enable stand-alone use per integration spec --- boltons/formatutils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/boltons/formatutils.py b/boltons/formatutils.py index 504c026d..7ce2deb9 100644 --- a/boltons/formatutils.py +++ b/boltons/formatutils.py @@ -41,7 +41,10 @@ import re from string import Formatter -from .namedutils import namedtuple +try: + from boltons.namedutils import namedtuple +except ImportError: + from collections import namedtuple __all__ = ['DeferredValue', 'get_format_args', 'tokenize_format_str', 'construct_format_field_str', 'infer_positional_format_args',