[diffoscope] 02/08: presenters: add PartialString.cont()

Ximin Luo infinity0 at debian.org
Wed Jul 5 21:59:08 CEST 2017


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch WIP/humungous-diffs
in repository diffoscope.

commit 3896da2bbed01a496fcc1b3713bb40f3d63fbc51
Author: Ximin Luo <infinity0 at debian.org>
Date:   Sat Jun 17 00:55:41 2017 +0200

    presenters: add PartialString.cont()
---
 diffoscope/presenters/utils.py | 35 +++++++++++++++++++++++++++++++----
 tests/test_presenters.py       | 10 ++++++++++
 2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/diffoscope/presenters/utils.py b/diffoscope/presenters/utils.py
index b0da209..69040d6 100644
--- a/diffoscope/presenters/utils.py
+++ b/diffoscope/presenters/utils.py
@@ -105,8 +105,11 @@ def create_limited_print_func(print_func, max_page_size):
 
 
 class Formatter(string.Formatter):
-    def arg_of_field_name(self, field_name):
-        return _string.formatter_field_name_split(field_name)[0]
+    def get_value(self, key, args, kwargs):
+        return args[key] if isinstance(key, int) else args[int(key)]
+    def arg_of_field_name(self, field_name, args):
+        x = int(_string.formatter_field_name_split(field_name)[0])
+        return x if x >= 0 else len(args) + x
 
 
 class FormatPlaceholder(object):
@@ -195,7 +198,7 @@ class PartialString(object):
         # Ensure the format string is valid, and figure out some basic stats
         fmt = self.formatter
         pieces = [(len(l), f) for l, f, _, _ in fmt.parse(fmtstr)]
-        used_args = set(fmt.arg_of_field_name(f) for _, f in pieces if f is not None)
+        used_args = set(fmt.arg_of_field_name(f, holes) for _, f in pieces if f is not None)
         self.num_holes = sum(1 for _, f in pieces if f is not None)
         self.base_len = sum(l for l, _ in pieces)
 
@@ -203,7 +206,7 @@ class PartialString(object):
         seen = collections.OrderedDict()
         mapping = tuple(FormatPlaceholder(seen.setdefault(k, len(seen))) if i in used_args else None
             for i, k in enumerate(holes))
-        self._fmtstr = fmt.vformat(fmtstr, mapping, {})
+        self._fmtstr = fmt.vformat(fmtstr, mapping, None)
         self.holes = tuple(seen.keys())
 
     def __eq__(self, other):
@@ -259,9 +262,33 @@ class PartialString(object):
         """
         return cls("{0}", obj)
 
+    @classmethod
+    def cont(cls):
+        r"""Create a new empty partial string with a continuation token.
+
+        Construct a larger partial string from smaller pieces, without having
+        to keep explicit track of a global index in between pieces. Instead,
+        you can use per-piece local indexes, plus the special index {-1} to
+        refer to where the next piece will go - or omit it to end the sequence.
+
+        >>> t, cont = PartialString.cont()
+        >>> t = cont(t, "x: {0}\ny: {1}\n{-1}", object(), object())
+        >>> t = cont(t, "z: {0}\n{-1}", object())
+        >>> t = cont(t, "")
+        >>> key = t.holes
+        >>> t.format({key[0]: "line1", key[1]: "line2", key[2]: "line3"})
+        'x: line1\ny: line2\nz: line3\n'
+        >>> t.size(hole_size=5)
+        27
+        """
+        def cont(t, fmtstr, *holes):
+            return t.pformat({cont: cls(fmtstr, *(holes + (cont,)))})
+        return cls("{0}", cont), cont
+
 
 if __name__ == "__main__":
     import doctest
     doctest.testmod(optionflags=doctest.ELLIPSIS)
     a, b = object(), object()
     tmpl = PartialString("{0} {1}", a, b)
+    t, cont = PartialString.cont()
diff --git a/tests/test_presenters.py b/tests/test_presenters.py
index 3e60c78..8fdaab9 100644
--- a/tests/test_presenters.py
+++ b/tests/test_presenters.py
@@ -168,3 +168,13 @@ def test_partial_string():
     PartialString("{1}", a, b)
     with pytest.raises(IndexError):
         PartialString("{0} {1} {2}", a, b)
+
+def test_partial_string_cont():
+    t, cont = PartialString.cont()
+    t = cont(t, "x: {0}\ny: {1}\n{-1}", object(), object())
+    t = cont(t, "z: {0}\n{-1}", object())
+    t = cont(t, "")
+    key = t.holes
+    assert (t.format({key[0]: "line1", key[1]: "line2", key[2]: "line3"})
+            == 'x: line1\ny: line2\nz: line3\n')
+    assert t.size(hole_size=5) == 27

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git


More information about the diffoscope mailing list