Hello community,

here is the log from the commit of package i18nspector for openSUSE:Factory 
checked in at 2020-12-01 14:22:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/i18nspector (Old)
 and      /work/SRC/openSUSE:Factory/.i18nspector.new.5913 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "i18nspector"

Tue Dec  1 14:22:54 2020 rev:31 rq:851928 version:0.26

Changes:
--------
--- /work/SRC/openSUSE:Factory/i18nspector/i18nspector.changes  2020-08-19 
18:59:10.219922002 +0200
+++ /work/SRC/openSUSE:Factory/.i18nspector.new.5913/i18nspector.changes        
2020-12-01 14:23:08.333616184 +0100
@@ -1,0 +2,11 @@
+Sun Nov 29 16:15:12 UTC 2020 - Kyrill Detinov <[email protected]>
+
+- Update to 0.26.
+  * Summary of tag changes:
+    + Added:
+     - perl-brace-format-string-error
+     - perl-brace-format-string-missing-argument
+     - perl-brace-format-string-unknown-argument
+  * Check for errors in Perl brace format strings.
+
+-------------------------------------------------------------------

Old:
----
  i18nspector-0.25.9.tar.gz
  i18nspector-0.25.9.tar.gz.asc

New:
----
  i18nspector-0.26.tar.gz
  i18nspector-0.26.tar.gz.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ i18nspector.spec ++++++
--- /var/tmp/diff_new_pack.77yQNq/_old  2020-12-01 14:23:09.017616924 +0100
+++ /var/tmp/diff_new_pack.77yQNq/_new  2020-12-01 14:23:09.021616928 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           i18nspector
-Version:        0.25.9
+Version:        0.26
 Release:        0
 Summary:        Tool for Checking gettext POT/PO/MO Files
 License:        MIT

++++++ i18nspector-0.25.9.tar.gz -> i18nspector-0.26.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/.pylintrc 
new/i18nspector-0.26/.pylintrc
--- old/i18nspector-0.25.9/.pylintrc    2020-08-06 10:23:02.000000000 +0200
+++ new/i18nspector-0.26/.pylintrc      2020-09-26 18:25:15.000000000 +0200
@@ -18,6 +18,7 @@
     no-else-raise,
     no-else-return,
     no-self-use,
+    raise-missing-from,
     redefined-variable-type,
     subprocess-popen-preexec-fn,
     superfluous-parens,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/data/tags 
new/i18nspector-0.26/data/tags
--- old/i18nspector-0.25.9/data/tags    2020-08-06 10:23:02.000000000 +0200
+++ new/i18nspector-0.26/data/tags      2020-09-26 18:25:15.000000000 +0200
@@ -709,6 +709,62 @@
 description =
  Translation is missing for some plural forms of a message.
 
+[perl-brace-format-string-error]
+severity = serious
+certainty = possible
+description =
+ A Perl format string could not be parsed.
+references =
+ https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html
+
+[perl-brace-format-string-missing-argument]
+severity = serious
+certainty = possible
+description =
+ A Perl format string for ``msgid`` doesn't use a named argument that is used 
in ``msgid_plural``;
+ or ``msgstr`` doesn't use a named argument that is used in ``msgid``;
+ or ``msgstr[``\ *N*\ ``]`` doesn't use a named argument that is used in 
corresponding ``msgid`` or ``msgid_plural``.
+ .
+ Note that in some languages,
+ the commonly used Plural-Forms expression evaluates to the same value for n=1 
and n=21, n=31, and so on.
+ Take this Serbian translation for example::
+ .
+ .  Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && 
n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
+ .  ...
+ .  msgid "one byte"
+ .  msgid_plural "{n} bytes"
+ .  msgstr[0] "{n} bajt"
+ .  msgstr[1] "{n} bajta"
+ .  msgstr[2] "{n} bajtova"
+ .
+ Here ``{n}`` should not be replaced with the spelled-out form ``jedan``.
+ Either ``{n}`` should be kept, or the Plural-Forms expression should be 
amended,
+ so that there is a special case for n=1::
+ .
+ .  Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : 
n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2
+ .  ...
+ .  msgid "one byte"
+ .  msgid_plural "{n} bytes"
+ .  msgstr[0] "{n} bajt"
+ .  msgstr[1] "{n} bajta"
+ .  msgstr[2] "{n} bajtova"
+ .  msgstr[3] "jedan bajt"
+references =
+ https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html
+ 
https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html
+
+[perl-brace-format-string-unknown-argument]
+severity = serious
+certainty = possible
+description =
+ A Perl format string for ``msgid`` uses a named argument that isn't used in 
``msgid_plural``;
+ or ``msgstr`` uses a named argument that isn't used in ``msgid``;
+ or ``msgstr[``\ *N*\ ``]`` uses a named argument that isn't used in 
corresponding ``msgid`` or ``msgid_plural``.
+ This indicates that the conversion would try to consume an argument that 
weren't supplied.
+references =
+ https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html
+ https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
+
 [python-brace-format-string-argument-type-mismatch]
 severity = serious
 certainty = possible
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/doc/changelog 
new/i18nspector-0.26/doc/changelog
--- old/i18nspector-0.25.9/doc/changelog        2020-08-06 10:23:02.000000000 
+0200
+++ new/i18nspector-0.26/doc/changelog  2020-09-26 18:25:15.000000000 +0200
@@ -1,3 +1,16 @@
+i18nspector (0.26) unstable; urgency=low
+
+  * Summary of tag changes:
+    + Added:
+      - perl-brace-format-string-error
+      - perl-brace-format-string-missing-argument
+      - perl-brace-format-string-unknown-argument
+
+  * Check for errors in Perl brace format strings.
+    https://github.com/jwilk/i18nspector/issues/6
+
+ -- Jakub Wilk <[email protected]>  Sat, 26 Sep 2020 18:25:06 +0200
+
 i18nspector (0.25.9) unstable; urgency=low
 
   * Drop support for Python < 3.4.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/doc/i18nspector.1 
new/i18nspector-0.26/doc/i18nspector.1
--- old/i18nspector-0.25.9/doc/i18nspector.1    2020-08-06 10:23:04.000000000 
+0200
+++ new/i18nspector-0.26/doc/i18nspector.1      2020-09-26 18:25:18.000000000 
+0200
@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH I18NSPECTOR 1 "2020-08-06" "i18nspector 0.25.9" ""
+.TH I18NSPECTOR 1 "2020-09-26" "i18nspector 0.26" ""
 .SH NAME
 i18nspector \- checking tool for gettext POT, PO and MO files
 .
@@ -1542,6 +1542,114 @@
 .sp
 Severity, certainty:
 .INDENT 0.0
+.INDENT 3.5
+serious, possible
+.UNINDENT
+.UNINDENT
+.SS perl\-brace\-format\-string\-error
+.sp
+A Perl format string could not be parsed.
+.sp
+References:
+.INDENT 0.0
+.INDENT 3.5
+.nf
+\fI\%https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html\fP
+.fi
+.sp
+.UNINDENT
+.UNINDENT
+.sp
+Severity, certainty:
+.INDENT 0.0
+.INDENT 3.5
+serious, possible
+.UNINDENT
+.UNINDENT
+.SS perl\-brace\-format\-string\-missing\-argument
+.sp
+A Perl format string for \fBmsgid\fP doesn't use a named argument that is used 
in \fBmsgid_plural\fP;
+or \fBmsgstr\fP doesn't use a named argument that is used in \fBmsgid\fP;
+or \fBmsgstr[\fP\fIN\fP\fB]\fP doesn't use a named argument that is used in 
corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&.
+.sp
+Note that in some languages,
+the commonly used Plural\-Forms expression evaluates to the same value for n=1 
and n=21, n=31, and so on.
+Take this Serbian translation for example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Plural\-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && 
n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
+\&...
+msgid "one byte"
+msgid_plural "{n} bytes"
+msgstr[0] "{n} bajt"
+msgstr[1] "{n} bajta"
+msgstr[2] "{n} bajtova"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Here \fB{n}\fP should not be replaced with the spelled\-out form \fBjedan\fP\&.
+Either \fB{n}\fP should be kept, or the Plural\-Forms expression should be 
amended,
+so that there is a special case for n=1:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Plural\-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : 
n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2
+\&...
+msgid "one byte"
+msgid_plural "{n} bytes"
+msgstr[0] "{n} bajt"
+msgstr[1] "{n} bajta"
+msgstr[2] "{n} bajtova"
+msgstr[3] "jedan bajt"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+References:
+.INDENT 0.0
+.INDENT 3.5
+.nf
+\fI\%https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html\fP
+\fI\%https://www.gnu.org/software/gettext/manual/html_node/Translating\-plural\-forms.html\fP
+.fi
+.sp
+.UNINDENT
+.UNINDENT
+.sp
+Severity, certainty:
+.INDENT 0.0
+.INDENT 3.5
+serious, possible
+.UNINDENT
+.UNINDENT
+.SS perl\-brace\-format\-string\-unknown\-argument
+.sp
+A Perl format string for \fBmsgid\fP uses a named argument that isn't used in 
\fBmsgid_plural\fP;
+or \fBmsgstr\fP uses a named argument that isn't used in \fBmsgid\fP;
+or \fBmsgstr[\fP\fIN\fP\fB]\fP uses a named argument that isn't used in 
corresponding \fBmsgid\fP or \fBmsgid_plural\fP\&.
+This indicates that the conversion would try to consume an argument that 
weren't supplied.
+.sp
+References:
+.INDENT 0.0
+.INDENT 3.5
+.nf
+\fI\%https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html\fP
+\fI\%https://www.gnu.org/software/gettext/manual/html_node/Plural\-forms.html\fP
+.fi
+.sp
+.UNINDENT
+.UNINDENT
+.sp
+Severity, certainty:
+.INDENT 0.0
 .INDENT 3.5
 serious, possible
 .UNINDENT
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/doc/manpage.rst 
new/i18nspector-0.26/doc/manpage.rst
--- old/i18nspector-0.25.9/doc/manpage.rst      2020-08-06 10:23:02.000000000 
+0200
+++ new/i18nspector-0.26/doc/manpage.rst        2020-09-26 18:25:15.000000000 
+0200
@@ -7,7 +7,7 @@
 ----------------------------------------------
 
 :manual section: 1
-:version: i18nspector 0.25.9
+:version: i18nspector 0.26
 :date: |date|
 
 Synopsis
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/doc/tags.rst 
new/i18nspector-0.26/doc/tags.rst
--- old/i18nspector-0.25.9/doc/tags.rst 2020-08-06 10:23:04.000000000 +0200
+++ new/i18nspector-0.26/doc/tags.rst   2020-09-26 18:25:17.000000000 +0200
@@ -974,6 +974,74 @@
 
  serious, possible
 
+perl-brace-format-string-error
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A Perl format string could not be parsed.
+
+References:
+
+ | https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html
+
+Severity, certainty:
+
+ serious, possible
+
+perl-brace-format-string-missing-argument
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A Perl format string for ``msgid`` doesn't use a named argument that is used 
in ``msgid_plural``;
+or ``msgstr`` doesn't use a named argument that is used in ``msgid``;
+or ``msgstr[``\ *N*\ ``]`` doesn't use a named argument that is used in 
corresponding ``msgid`` or ``msgid_plural``.
+
+Note that in some languages,
+the commonly used Plural-Forms expression evaluates to the same value for n=1 
and n=21, n=31, and so on.
+Take this Serbian translation for example::
+
+  Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && 
n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
+  ...
+  msgid "one byte"
+  msgid_plural "{n} bytes"
+  msgstr[0] "{n} bajt"
+  msgstr[1] "{n} bajta"
+  msgstr[2] "{n} bajtova"
+
+Here ``{n}`` should not be replaced with the spelled-out form ``jedan``.
+Either ``{n}`` should be kept, or the Plural-Forms expression should be 
amended,
+so that there is a special case for n=1::
+
+  Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : 
n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2
+  ...
+  msgid "one byte"
+  msgid_plural "{n} bytes"
+  msgstr[0] "{n} bajt"
+  msgstr[1] "{n} bajta"
+  msgstr[2] "{n} bajtova"
+  msgstr[3] "jedan bajt"
+
+References:
+
+ | https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html
+ | 
https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html
+
+Severity, certainty:
+
+ serious, possible
+
+perl-brace-format-string-unknown-argument
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A Perl format string for ``msgid`` uses a named argument that isn't used in 
``msgid_plural``;
+or ``msgstr`` uses a named argument that isn't used in ``msgid``;
+or ``msgstr[``\ *N*\ ``]`` uses a named argument that isn't used in 
corresponding ``msgid`` or ``msgid_plural``.
+This indicates that the conversion would try to consume an argument that 
weren't supplied.
+
+References:
+
+ | https://www.gnu.org/software/gettext/manual/html_node/perl_002dformat.html
+ | https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
+
+Severity, certainty:
+
+ serious, possible
+
 python-brace-format-string-argument-type-mismatch
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 There's a type mismatch between a Python format argument in ``msgid`` and the 
corresponding format argument in ``msgid_plural``;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/lib/check/__init__.py 
new/i18nspector-0.26/lib/check/__init__.py
--- old/i18nspector-0.25.9/lib/check/__init__.py        2020-08-06 
10:23:02.000000000 +0200
+++ new/i18nspector-0.26/lib/check/__init__.py  2020-09-26 18:25:15.000000000 
+0200
@@ -44,6 +44,7 @@
 from lib import xml
 
 from lib.check.msgformat import c as msgformat_c
+from lib.check.msgformat import perlbrace as msgformat_perlbrace
 from lib.check.msgformat import pybrace as msgformat_pybrace
 from lib.check.msgformat import python as msgformat_python
 from lib.check.msgrepr import message_repr
@@ -101,6 +102,7 @@
         self.options = options
         self._message_format_checkers = {
             'c': msgformat_c.Checker(self),
+            'perl-brace': msgformat_perlbrace.Checker(self),
             'python': msgformat_python.Checker(self),
             'python-brace': msgformat_pybrace.Checker(self),
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/lib/check/msgformat/perlbrace.py 
new/i18nspector-0.26/lib/check/msgformat/perlbrace.py
--- old/i18nspector-0.25.9/lib/check/msgformat/perlbrace.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/i18nspector-0.26/lib/check/msgformat/perlbrace.py       2020-09-26 
18:25:15.000000000 +0200
@@ -0,0 +1,70 @@
+# Copyright © 2016-2020 Jakub Wilk <[email protected]>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the “Software”), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+'''
+message format checks: Perl Locale::TextDomain
+'''
+
+from lib import tags
+
+from lib.check.msgformat import Checker as CheckerBase
+from lib.check.msgrepr import message_repr
+
+from lib.strformat import perlbrace as backend
+
+class Checker(CheckerBase):
+
+    backend = backend  # pylint: disable=self-assigning-variable
+
+    def check_string(self, ctx, message, s):
+        prefix = message_repr(message, template='{}:')
+        fmt = None
+        try:
+            fmt = backend.FormatString(s)
+        except backend.Error as exc:
+            self.tag('perl-brace-format-string-error',
+                prefix,
+                tags.safestr(exc.message),
+                *exc.args[:1]
+            )
+        else:
+            return fmt
+
+    def check_args(self, message, src_loc, src_fmt, dst_loc, dst_fmt, *, 
omitted_int_conv_ok=False):
+        def sort_key(item):
+            return (isinstance(item, str), item)
+        prefix = message_repr(message, template='{}:')
+        src_args = src_fmt.arguments
+        dst_args = dst_fmt.arguments
+        for key in sorted(dst_args - src_args, key=sort_key):
+            self.tag('perl-brace-format-string-unknown-argument', prefix, key,
+                tags.safestr('in'), tags.safestr(dst_loc),
+                tags.safestr('but not in'), tags.safestr(src_loc),
+            )
+        missing_keys = src_args - dst_args
+        if len(missing_keys) == 1 and omitted_int_conv_ok:
+            missing_keys = ()
+        for key in sorted(missing_keys):
+            self.tag('perl-brace-format-string-missing-argument', prefix, key,
+                tags.safestr('not in'), tags.safestr(dst_loc),
+                tags.safestr('while in'), tags.safestr(src_loc),
+            )
+
+# vim:ts=4 sts=4 sw=4 et
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/lib/cli.py 
new/i18nspector-0.26/lib/cli.py
--- old/i18nspector-0.25.9/lib/cli.py   2020-08-06 10:23:02.000000000 +0200
+++ new/i18nspector-0.26/lib/cli.py     2020-09-26 18:25:15.000000000 +0200
@@ -39,7 +39,7 @@
 from lib import tags
 from lib import terminal
 
-__version__ = '0.25.9'
+__version__ = '0.26'
 
 def initialize_terminal():
     if sys.stdout.isatty():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/lib/strformat/perlbrace.py 
new/i18nspector-0.26/lib/strformat/perlbrace.py
--- old/i18nspector-0.25.9/lib/strformat/perlbrace.py   1970-01-01 
01:00:00.000000000 +0100
+++ new/i18nspector-0.26/lib/strformat/perlbrace.py     2020-09-26 
18:25:15.000000000 +0200
@@ -0,0 +1,70 @@
+# Copyright © 2016-2020 Jakub Wilk <[email protected]>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the “Software”), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+'''
+Perl format checks: Locale::TextDomain
+'''
+
+import re
+
+_field_re = re.compile(r'''
+    (?P<literal> [^{]+ ) |
+    (?:
+        [{]
+            (?P<name> [^\W\d]\w* )
+        [}]
+    )
+''', re.VERBOSE)
+
+def _printable_prefix(s, r=re.compile('[ -\x7E]+')):
+    return r.match(s).group()
+
+class Error(Exception):
+    message = 'invalid placeholder specification'
+
+class FormatString():
+
+    def __init__(self, s):
+        self._items = items = []
+        arguments = set()
+        last_pos = 0
+        for match in _field_re.finditer(s):
+            if match.start() != last_pos:
+                raise Error(
+                    _printable_prefix(s[last_pos:])
+                )
+            items += [match.group()]
+            argname = match.group('name')
+            if argname is not None:
+                arguments.add(argname)
+            last_pos = match.end()
+        if last_pos != len(s):
+            raise Error(
+                _printable_prefix(s[last_pos:])
+            )
+        self.arguments = frozenset(arguments)
+
+    def __iter__(self):
+        return iter(self._items)
+
+    def __len__(self):
+        return len(self._items)
+
+# vim:ts=4 sts=4 sw=4 et
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/lib/strformat/pybrace.py 
new/i18nspector-0.26/lib/strformat/pybrace.py
--- old/i18nspector-0.25.9/lib/strformat/pybrace.py     2020-08-06 
10:23:02.000000000 +0200
+++ new/i18nspector-0.26/lib/strformat/pybrace.py       2020-09-26 
18:25:15.000000000 +0200
@@ -1,4 +1,4 @@
-# Copyright © 2016-2018 Jakub Wilk <[email protected]>
+# Copyright © 2016-2020 Jakub Wilk <[email protected]>
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the “Software”), to deal
@@ -40,7 +40,7 @@
 
 _field_re = re.compile(r'''
     (?P<literal> (?: [^{}] | [{]{2} | [}]{2} )+ ) |
-    (
+    (?:
         [{]
             (?:
                 (?P<name>''' + _field_name_pattern + r''') ?
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/private/online-build-po-corpus 
new/i18nspector-0.26/private/online-build-po-corpus
--- old/i18nspector-0.25.9/private/online-build-po-corpus       2020-08-06 
10:23:02.000000000 +0200
+++ new/i18nspector-0.26/private/online-build-po-corpus 2020-09-26 
18:25:15.000000000 +0200
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 
-# Copyright © 2012-2019 Jakub Wilk <[email protected]>
+# Copyright © 2012-2020 Jakub Wilk <[email protected]>
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the “Software”), to deal
@@ -46,8 +46,10 @@
         self._files = []
         self._tmpdir = 
tempfile.TemporaryDirectory(prefix='i18nspector.private.')
 
-    def add(self, url, name):
-        url = urllib.parse.urljoin(self._urlbase, url)
+    def add(self, url, name, urlbase=None):
+        if urlbase is None:
+            urlbase = self._urlbase
+        url = urllib.parse.urljoin(urlbase, url)
         self._files += [apt_pkg.AcquireFile(
             self._acquire,
             uri=url,
@@ -99,6 +101,9 @@
     ap.add_argument('--mirror', metavar='URL', default=default_mirror,
         help='Debian mirror to use (default: 
{mirror})'.format(mirror=default_mirror)
     )
+    ap.add_argument('--contents-mirror', metavar='URL', default=None,
+        help='Debian mirror of Contents-* files to use (default: same as 
--mirror)'
+    )
     ap.add_argument('--distribution', metavar='DIST', default=default_dist,
         help='Debian distribution to use (default: 
{dist})'.format(dist=default_dist)
     )
@@ -117,6 +122,9 @@
             break
     tar = tarfile.open(output, mode=tarmode)
     mirror = options.mirror
+    cnts_mirror = options.contents_mirror
+    if cnts_mirror is None:
+        cnts_mirror = mirror
     dist = options.distribution
     areas = options.areas.split(',')
     def tarfilter(tarinfo):
@@ -126,13 +134,17 @@
         tarinfo.mode |= 0o644
         if tarinfo.mode & 0o100:
             tarinfo.mode |= 0o111
-        tarinfo.name = 'po-corpus-{dist}/{name}'.format(dist=dist, 
name=tarinfo.name)
+        prefix = 'po-corpus-{dist}/'.format(dist=dist)
+        tarinfo.name = prefix + tarinfo.name
+        if tarinfo.linkname:
+            tarinfo.linkname = prefix + tarinfo.linkname
         return tarinfo
     subprocess.check_call(['dpkg-source', '--version'], 
stdout=subprocess.DEVNULL)
     for area in areas:
         urlbase = '{mirror}/dists/{dist}/{area}/'.format(mirror=mirror, 
dist=dist, area=area)
+        cnts_urlbase = 
'{mirror}/dists/{dist}/{area}/'.format(mirror=cnts_mirror, dist=dist, area=area)
         with Fetcher(urlbase=urlbase) as fetcher:
-            fetcher.add('Contents-source.gz', 'Contents.gz')
+            fetcher.add('Contents-source.gz', 'Contents.gz', 
urlbase=cnts_urlbase)
             fetcher.add('source/Sources.xz', 'Sources.xz')
             [contents_path, sources_path] = fetcher.run()
             interesting_packages = set()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/private/tags-as-rst 
new/i18nspector-0.26/private/tags-as-rst
--- old/i18nspector-0.25.9/private/tags-as-rst  2020-08-06 10:23:02.000000000 
+0200
+++ new/i18nspector-0.26/private/tags-as-rst    2020-09-26 18:25:15.000000000 
+0200
@@ -44,7 +44,7 @@
             for ref in tag.references:
                 match = 
re.match(r'\A(?P<name>[\w-]+)[(](?P<section>[0-9])[)]\Z', ref)
                 if match is not None:
-                    ref = r'**{name}**\ 
({section})'.format(**match.groupdict())
+                    ref = r'**{name}**\ 
({section})'.format_map(match.groupdict())
                 print(' |', ref)
             print()
         print('Severity, certainty:', end='\n\n')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-error.po 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-error.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-error.po   
    1970-01-01 01:00:00.000000000 +0100
+++ new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-error.po 
2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,18 @@
+# E: perl-brace-format-string-error msgid 'A quick brown fox jumps over the 
lazy dog.': invalid placeholder specification '{'
+
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Latin <[email protected]>\n"
+"Language: la\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, perl-brace-format
+msgid "A quick brown fox jumps over the lazy dog."
+msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis{"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-missing-argument.po
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-missing-argument.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-missing-argument.po
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-missing-argument.po
      2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,18 @@
+# E: perl-brace-format-string-missing-argument msgid 'A quick brown {A} jumps 
over the lazy {B}': A not in msgstr while in msgid
+
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Latin <[email protected]>\n"
+"Language: la\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, perl-brace-format
+msgid "A quick brown {A} jumps over the lazy {B}"
+msgstr "Sic fugiens, dux, zelotypos, quam {B} haberis."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-missing-arguments.pot
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-missing-arguments.pot
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-missing-arguments.pot
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-missing-arguments.pot
    2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,23 @@
+# E: perl-brace-format-string-missing-argument msgid 'A quick brown fox jumps 
over the lazy dog.': N not in msgid while in msgid_plural
+# E: perl-brace-format-string-missing-argument msgid 'A quick brown fox jumps 
over the lazy dog.': X not in msgid while in msgid_plural
+
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <[email protected]>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#, perl-brace-format
+msgid "A quick brown fox jumps over the lazy dog."
+msgid_plural "{N} quick brown foxes jump over the lazy {X}."
+msgstr[0] ""
+msgstr[1] ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-missing-numeral.po
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-missing-numeral.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-missing-numeral.po
     1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-missing-numeral.po
       2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,22 @@
+# E: perl-brace-format-string-missing-argument msgid once: N not in msgstr[0] 
while in msgid_plural
+
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Russian <[email protected]>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && 
n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"
+
+#, perl-brace-format
+msgid "once"
+msgid_plural "{N} times"
+msgstr[0] "paз"
+msgstr[1] "{N} paзи"
+msgstr[2] "{N} paзiв"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-msgid-error.po
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-msgid-error.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-msgid-error.po
 1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-msgid-error.po
   2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,16 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Latin <[email protected]>\n"
+"Language: la\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, perl-brace-format
+msgid "A quick brown fox jumps over the lazy dog{"
+msgstr "Sic fugiens, dux, zelotypos, quam Karus haberis{"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-msgid-error.pot
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-msgid-error.pot
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-msgid-error.pot
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-msgid-error.pot
  2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,19 @@
+# E: perl-brace-format-string-error msgid 'A quick brown fox jumps over the 
lazy dog{': invalid placeholder specification '{'
+
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <[email protected]>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, perl-brace-format
+msgid "A quick brown fox jumps over the lazy dog{"
+msgstr ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-no-excess-arguments.po
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-no-excess-arguments.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-no-excess-arguments.po
 1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-no-excess-arguments.po
   2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,20 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Russian <[email protected]>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && 
n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"
+
+#, perl-brace-format
+msgid "once"
+msgid_plural "{N} times"
+msgstr[0] "{N} paз"
+msgstr[1] "{N} paзи"
+msgstr[2] "{N} paзiв"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-okay.po 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-okay.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-okay.po    
    1970-01-01 01:00:00.000000000 +0100
+++ new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-okay.po  
2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,16 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Latin <[email protected]>\n"
+"Language: la\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, perl-brace-format
+msgid "A quick brown {X} jumps over the lazy dog."
+msgstr "Sic fugiens, {X}, zelotypos, quam Karus haberis."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-okay.pot 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-okay.pot
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-okay.pot   
    1970-01-01 01:00:00.000000000 +0100
+++ new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-okay.pot 
2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,17 @@
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <[email protected]>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, perl-brace-format
+msgid "A quick brown {X} jumps over the lazy dog."
+msgstr ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-1.po
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-1.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-1.po
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-1.po
     2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,20 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Polish <[email protected]>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 
|| n%100>=20) ? 1 : 2;\n"
+
+#, perl-brace-format
+msgid "{N} quick brown fox jumps over the lazy dog."
+msgid_plural "{N} quick brown foxes jump over the lazy dog."
+msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę."
+msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi."
+msgstr[2] "Mężny bądź, chroń pułk twój i {N} flag."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-2.po
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-2.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-2.po
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-2.po
     2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,20 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Polish <[email protected]>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 
|| n%100>=20) ? 1 : 2;\n"
+
+#, perl-brace-format
+msgid "A quick brown fox jumps over the lazy dog."
+msgid_plural "{N} quick brown foxes jump over the lazy dog."
+msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę."
+msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi."
+msgstr[2] "Mężny bądź, chroń pułk twój i {N} flag."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-5.po
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-5.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-5.po
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral-5.po
     2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,37 @@
+# E: perl-brace-format-string-missing-argument msgid 'A quick brown fox jumps 
over the lazy dog.' msgctxt 'max 6': N not in msgstr[2] while in msgid_plural
+
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Polish <[email protected]>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 
|| n%100>=20) ? 1 : 2;\n"
+
+# {N} doesn't have to be included in msgstr[2], because according to the range
+# flag, it applies only to n=5.
+
+#, perl-brace-format, range: 1..5
+msgctxt "max 5"
+msgid "A quick brown fox jumps over the lazy dog."
+msgid_plural "{N} quick brown foxes jump over the lazy dog."
+msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę."
+msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi."
+msgstr[2] "Mężny bądź, chroń pułk twój i pięć flag."
+
+# {N} cannot be omitted in msgstr[2], because it applies not only to n=5 but
+# also n=6.
+
+#, perl-brace-format, range: 1..6
+msgctxt "max 6"
+msgid "A quick brown fox jumps over the lazy dog."
+msgid_plural "{N} quick brown foxes jump over the lazy dog."
+msgstr[0] "Mężny bądź, chroń pułk twój i jedną flagę."
+msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi."
+msgstr[2] "Mężny bądź, chroń pułk twój i pięć flag."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-omitted-numeral.pot
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral.pot
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-omitted-numeral.pot
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-omitted-numeral.pot
      2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,20 @@
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <[email protected]>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#, perl-brace-format
+msgid "A quick brown fox jumps over the lazy dog."
+msgid_plural "{N} quick brown foxes jump over the lazy dog."
+msgstr[0] ""
+msgstr[1] ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-plural-okay.po
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-plural-okay.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-plural-okay.po
 1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-plural-okay.po
   2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,20 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Polish <[email protected]>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 
|| n%100>=20) ? 1 : 2;\n"
+
+#, perl-brace-format
+msgid "{N} quick brown fox jumps over the lazy dog."
+msgid_plural "{N} quick brown foxes jump over the lazy dog."
+msgstr[0] "Mężny bądź, chroń pułk twój i {N} flagę."
+msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi."
+msgstr[2] "Mężny bądź, chroń pułk twój i {N} flag."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-plural-okay.pot
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-plural-okay.pot
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-plural-okay.pot
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-plural-okay.pot
  2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,20 @@
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <[email protected]>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#, perl-brace-format
+msgid "{N} quick brown fox jumps over the lazy dog."
+msgid_plural "{N} quick brown foxes jump over the lazy dog."
+msgstr[0] ""
+msgstr[1] ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-unknown-argument-1.po
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-unknown-argument-1.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-unknown-argument-1.po
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-unknown-argument-1.po
    2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,18 @@
+# E: perl-brace-format-string-unknown-argument msgid 'A quick brown {A} jumps 
over the lazy dog.': B in msgstr but not in msgid
+
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Latin <[email protected]>\n"
+"Language: la\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#, perl-brace-format
+msgid "A quick brown {A} jumps over the lazy dog."
+msgstr "Sic fugiens, {A}, zelotypos, quam {B} haberis."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-unknown-argument-2.po
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-unknown-argument-2.po
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-unknown-argument-2.po
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-unknown-argument-2.po
    2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,23 @@
+# E: perl-brace-format-string-unknown-argument msgid '{N} quick brown fox 
jumps over the lazy dog.': O in msgstr[0] but not in msgid
+# E: perl-brace-format-string-unknown-argument msgid '{N} quick brown fox 
jumps over the lazy dog.': O in msgstr[2] but not in msgid_plural
+
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: 2012-11-01 14:42+0100\n"
+"Last-Translator: Jakub Wilk <[email protected]>\n"
+"Language-Team: Polish <[email protected]>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 
|| n%100>=20) ? 1 : 2;\n"
+
+#, perl-brace-format
+msgid "{N} quick brown fox jumps over the lazy dog."
+msgid_plural "{N} quick brown foxes jump over the lazy dog."
+msgstr[0] "Mężny bądź, chroń {O} twój i {N} flagę."
+msgstr[1] "Mężny bądź, chroń pułk twój i {N} flagi."
+msgstr[2] "Mężny bądź, chroń {O} twój i {N} flag."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-unknown-argument.pot
 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-unknown-argument.pot
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/perl-brace-format-string-unknown-argument.pot
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/i18nspector-0.26/tests/blackbox_tests/perl-brace-format-string-unknown-argument.pot
     2020-09-26 18:25:15.000000000 +0200
@@ -0,0 +1,22 @@
+# E: perl-brace-format-string-unknown-argument msgid '{N} quick brown fox 
jumps over the lazy dog.': N in msgid but not in msgid_plural
+
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Gizmo Enhancer 1.0\n"
+"Report-Msgid-Bugs-To: [email protected]\n"
+"POT-Creation-Date: 2012-11-01 14:42+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <[email protected]>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#, perl-brace-format
+msgid "{N} quick brown fox jumps over the lazy dog."
+msgid_plural "Quick brown foxes jump over the lazy dog."
+msgstr[0] ""
+msgstr[1] ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/i18nspector-0.25.9/tests/blackbox_tests/python-brace-format-string-missing-non-numeral.pot
 
new/i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-missing-non-numeral.pot
--- 
old/i18nspector-0.25.9/tests/blackbox_tests/python-brace-format-string-missing-non-numeral.pot
      2020-08-06 10:23:02.000000000 +0200
+++ 
new/i18nspector-0.26/tests/blackbox_tests/python-brace-format-string-missing-non-numeral.pot
        2020-09-26 18:25:15.000000000 +0200
@@ -20,4 +20,3 @@
 msgid_plural "{N:s} quick brown foxes jump over the lazy dog."
 msgstr[0] ""
 msgstr[1] ""
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/tests/coverage 
new/i18nspector-0.26/tests/coverage
--- old/i18nspector-0.25.9/tests/coverage       2020-08-06 10:23:02.000000000 
+0200
+++ new/i18nspector-0.26/tests/coverage 2020-09-26 18:25:15.000000000 +0200
@@ -1,31 +1,33 @@
 Generated automatically by private/update-branch-coverage. Do not edit.
 
-Name                              Stmts   Miss Branch BrPart  Cover   Missing
------------------------------------------------------------------------------
-lib/__init__.py                       1      0      0      0   100%
-lib/check/__init__.py               809    749    515      0     5%   82-86, 
89-102, 116-201, 204-220, 224-356, 360-504, 508-580, 584-627, 632-667, 672-716, 
719-797, 800-880, 883-997, 1000-1007, 1010-1026, 1031
-lib/check/msgformat/__init__.py      83     68     36      0    13%   31, 38, 
41-151
-lib/check/msgformat/c.py             67     56     36      0    11%   37-44, 
47-105, 108-129
-lib/check/msgformat/pybrace.py       35     26     13      0    19%   37-48, 
51-75
-lib/check/msgformat/python.py        77     67     47      0     8%   37-109, 
112-149
-lib/check/msgrepr.py                 11      7      2      0    31%   28-34
-lib/cli.py                          161    125     46      0    17%   45-49, 
58-67, 70-71, 74-76, 82-111, 114-119, 125-131, 134-142, 145-153, 159, 168-186, 
189-195, 198-232
-lib/domains.py                       15      0      0      0   100%
-lib/encodings.py                    132     38     36      2    73%   50-66, 
78-86, 134->138, 138-140, 191->193, 193, 207-220, 224-228
-lib/gettext.py                      105      0     36      0   100%
-lib/iconv.py                        156     49     58     19    64%   41-42, 
55-57, 63->64, 64, 65->66, 66, 67->68, 68, 69->70, 70, 82->83, 83-84, 96->97, 
97-98, 105->110, 110->111, 111-123, 129->130, 129->exit, 130-131, 134-145, 
150->151, 151, 152->153, 153, 154->155, 155, 156->157, 157, 165->166, 166-167, 
179->180, 180-181, 198->213, 200->203, 203-204, 213, 221->222, 222-223, 226-237
-lib/intexpr.py                      420      0    126      0   100%
-lib/ling.py                         243      2     98      3    99%   
159->162, 179->181, 181, 277->283, 281
-lib/misc.py                          42      0     16      0   100%
-lib/moparser.py                     138     92     56      3    28%   56->58, 
68, 74->76, 76, 91-109, 112-178, 183-192, 194->195, 195
-lib/paths.py                          7      2      0      0    71%   36-37
-lib/polib4us.py                     120     75     26      0    31%   41-42, 
56, 72, 75-96, 100, 110-112, 133-145, 149, 161, 170-175, 186-194, 205, 208, 
212-216, 228-235, 243-252
-lib/strformat/__init__.py             0      0      0      0   100%
-lib/strformat/c.py                  285      0    168      0   100%
-lib/strformat/pybrace.py            156      0     74      0   100%
-lib/strformat/python.py             204      0     94      0   100%
-lib/tags.py                         117     29     34      4    75%   81->82, 
82, 83->84, 84, 86->87, 87, 106-107, 118-120, 125-127, 139->140, 140, 151-158, 
164-168, 178-191, 210, 216
-lib/terminal.py                      48     17      6      1    59%   37-38, 
63->64, 64, 80-93
-lib/xml.py                           21      0      2      0   100%
------------------------------------------------------------------------------
-TOTAL                              3453   1402   1525     32    55%
+Name                               Stmts   Miss Branch BrPart  Cover   Missing
+------------------------------------------------------------------------------
+lib/__init__.py                        1      0      0      0   100%
+lib/check/__init__.py                810    749    515      0     5%   83-87, 
90-103, 118-203, 206-222, 226-358, 362-506, 510-582, 586-629, 634-669, 674-718, 
721-799, 802-882, 885-999, 1002-1009, 1012-1028, 1033
+lib/check/msgformat/__init__.py       83     68     36      0    13%   31, 38, 
41-151
+lib/check/msgformat/c.py              67     56     36      0    11%   37-44, 
47-105, 108-129
+lib/check/msgformat/perlbrace.py      28     19      6      0    26%   37-48, 
51-65
+lib/check/msgformat/pybrace.py        35     26     13      0    19%   37-48, 
51-75
+lib/check/msgformat/python.py         77     67     47      0     8%   37-109, 
112-149
+lib/check/msgrepr.py                  11      7      2      0    31%   28-34
+lib/cli.py                           161    125     46      0    17%   45-49, 
58-67, 70-71, 74-76, 82-111, 114-119, 125-131, 134-142, 145-153, 159, 168-186, 
189-195, 198-232
+lib/domains.py                        15      0      0      0   100%
+lib/encodings.py                     134     40     36      2    72%   50-66, 
78-86, 134->138, 138-142, 193->195, 195, 209-222, 226-230
+lib/gettext.py                       105      0     36      0   100%
+lib/iconv.py                         156     49     58     19    64%   41-42, 
55-57, 63->64, 64, 65->66, 66, 67->68, 68, 69->70, 70, 82->83, 83-84, 96->97, 
97-98, 105->110, 110->111, 111-123, 129->130, 129->exit, 130-131, 134-145, 
150->151, 151, 152->153, 153, 154->155, 155, 156->157, 157, 165->166, 166-167, 
179->180, 180-181, 198->213, 200->203, 203-204, 213, 221->222, 222-223, 226-237
+lib/intexpr.py                       420      0    126      0   100%
+lib/ling.py                          243      2     98      3    99%   
159->162, 179->181, 181, 277->283, 281
+lib/misc.py                           42      0     16      0   100%
+lib/moparser.py                      138     92     56      3    28%   56->58, 
68, 74->76, 76, 91-109, 112-178, 183-192, 194->195, 195
+lib/paths.py                           7      2      0      0    71%   36-37
+lib/polib4us.py                      120     75     26      0    31%   41-42, 
56, 72, 75-96, 100, 110-112, 133-145, 149, 161, 170-175, 186-194, 205, 208, 
212-216, 228-235, 243-252
+lib/strformat/__init__.py              0      0      0      0   100%
+lib/strformat/c.py                   285      0    168      0   100%
+lib/strformat/perlbrace.py            27      0      8      0   100%
+lib/strformat/pybrace.py             156      0     74      0   100%
+lib/strformat/python.py              204      0     94      0   100%
+lib/tags.py                          117     29     34      4    75%   81->82, 
82, 83->84, 84, 86->87, 87, 106-107, 118-120, 125-127, 139->140, 140, 151-158, 
164-168, 178-191, 210, 216
+lib/terminal.py                       48     17      6      1    59%   37-38, 
63->64, 64, 80-93
+lib/xml.py                            21      0      2      0   100%
+------------------------------------------------------------------------------
+TOTAL                               3511   1423   1539     32    55%
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i18nspector-0.25.9/tests/test_strformat_perlbrace.py 
new/i18nspector-0.26/tests/test_strformat_perlbrace.py
--- old/i18nspector-0.25.9/tests/test_strformat_perlbrace.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/i18nspector-0.26/tests/test_strformat_perlbrace.py      2020-09-26 
18:25:15.000000000 +0200
@@ -0,0 +1,57 @@
+# Copyright © 2016-2020 Jakub Wilk <[email protected]>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the “Software”), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+from nose.tools import (
+    assert_equal,
+    assert_raises,
+)
+
+import lib.strformat.perlbrace as M
+
+def test_lone_lcb():
+    with assert_raises(M.Error):
+        M.FormatString('{')
+
+def test_lone_rcb():
+    M.FormatString('}')
+
+def test_invalid_field():
+    with assert_raises(M.Error):
+        M.FormatString('{@}')
+
+def test_text():
+    fmt = M.FormatString('bacon')
+    assert_equal(len(fmt), 1)
+    [fld] = fmt
+    assert_equal(fld, 'bacon')
+
+class test_named_arguments:
+
+    def test_good(self):
+        fmt = M.FormatString('{spam}')
+        assert_equal(len(fmt), 1)
+        [fld] = fmt
+        assert_equal(fld, '{spam}')
+
+    def test_bad(self):
+        with assert_raises(M.Error):
+            M.FormatString('{3ggs}')
+
+# vim:ts=4 sts=4 sw=4 et
_______________________________________________
openSUSE Commits mailing list -- [email protected]
To unsubscribe, email [email protected]
List Netiquette: https://en.opensuse.org/openSUSE:Mailing_list_netiquette
List Archives: 
https://lists.opensuse.org/archives/list/[email protected]

Reply via email to