mercurial/match.py
changeset 43076 2372284d9457
parent 42864 72890d8f9860
child 43077 687b865b95ad
--- a/mercurial/match.py	Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/match.py	Sun Oct 06 09:45:02 2019 -0400
@@ -21,20 +21,30 @@
     pycompat,
     util,
 )
-from .utils import (
-    stringutil,
-)
+from .utils import stringutil
 
 rustmod = policy.importrust(r'filepatterns')
 
-allpatternkinds = ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
-                   'rootglob',
-                   'listfile', 'listfile0', 'set', 'include', 'subinclude',
-                   'rootfilesin')
+allpatternkinds = (
+    're',
+    'glob',
+    'path',
+    'relglob',
+    'relpath',
+    'relre',
+    'rootglob',
+    'listfile',
+    'listfile0',
+    'set',
+    'include',
+    'subinclude',
+    'rootfilesin',
+)
 cwdrelativepatternkinds = ('relpath', 'glob')
 
 propertycache = util.propertycache
 
+
 def _rematcher(regex):
     '''compile the regexp with the best available regexp engine and return a
     matcher function'''
@@ -45,6 +55,7 @@
     except AttributeError:
         return m.match
 
+
 def _expandsets(kindpats, ctx=None, listsubrepos=False, badfn=None):
     '''Returns the kindpats list with the 'set' patterns expanded to matchers'''
     matchers = []
@@ -53,8 +64,9 @@
     for kind, pat, source in kindpats:
         if kind == 'set':
             if ctx is None:
-                raise error.ProgrammingError("fileset expression with no "
-                                             "context")
+                raise error.ProgrammingError(
+                    "fileset expression with no " "context"
+                )
             matchers.append(ctx.matchfileset(pat, badfn=badfn))
 
             if listsubrepos:
@@ -67,6 +79,7 @@
         other.append((kind, pat, source))
     return matchers, other
 
+
 def _expandsubinclude(kindpats, root):
     '''Returns the list of subinclude matcher args and the kindpats without the
     subincludes in it.'''
@@ -91,6 +104,7 @@
 
     return relmatchers, other
 
+
 def _kindpatsalwaysmatch(kindpats):
     """"Checks whether the kindspats match everything, as e.g.
     'relpath:.' does.
@@ -100,11 +114,14 @@
             return False
     return True
 
-def _buildkindpatsmatcher(matchercls, root, kindpats, ctx=None,
-                          listsubrepos=False, badfn=None):
+
+def _buildkindpatsmatcher(
+    matchercls, root, kindpats, ctx=None, listsubrepos=False, badfn=None
+):
     matchers = []
-    fms, kindpats = _expandsets(kindpats, ctx=ctx,
-                                listsubrepos=listsubrepos, badfn=badfn)
+    fms, kindpats = _expandsets(
+        kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=badfn
+    )
     if kindpats:
         m = matchercls(root, kindpats, badfn=badfn)
         matchers.append(m)
@@ -116,9 +133,21 @@
         return matchers[0]
     return unionmatcher(matchers)
 
-def match(root, cwd, patterns=None, include=None, exclude=None, default='glob',
-          auditor=None, ctx=None, listsubrepos=False, warn=None,
-          badfn=None, icasefs=False):
+
+def match(
+    root,
+    cwd,
+    patterns=None,
+    include=None,
+    exclude=None,
+    default='glob',
+    auditor=None,
+    ctx=None,
+    listsubrepos=False,
+    warn=None,
+    badfn=None,
+    icasefs=False,
+):
     r"""build an object to match a set of file patterns
 
     arguments:
@@ -223,8 +252,14 @@
         if _kindpatsalwaysmatch(kindpats):
             m = alwaysmatcher(badfn)
         else:
-            m = _buildkindpatsmatcher(patternmatcher, root, kindpats, ctx=ctx,
-                                      listsubrepos=listsubrepos, badfn=badfn)
+            m = _buildkindpatsmatcher(
+                patternmatcher,
+                root,
+                kindpats,
+                ctx=ctx,
+                listsubrepos=listsubrepos,
+                badfn=badfn,
+            )
     else:
         # It's a little strange that no patterns means to match everything.
         # Consider changing this to match nothing (probably using nevermatcher).
@@ -232,25 +267,41 @@
 
     if include:
         kindpats = normalize(include, 'glob', root, cwd, auditor, warn)
-        im = _buildkindpatsmatcher(includematcher, root, kindpats, ctx=ctx,
-                                   listsubrepos=listsubrepos, badfn=None)
+        im = _buildkindpatsmatcher(
+            includematcher,
+            root,
+            kindpats,
+            ctx=ctx,
+            listsubrepos=listsubrepos,
+            badfn=None,
+        )
         m = intersectmatchers(m, im)
     if exclude:
         kindpats = normalize(exclude, 'glob', root, cwd, auditor, warn)
-        em = _buildkindpatsmatcher(includematcher, root, kindpats, ctx=ctx,
-                                   listsubrepos=listsubrepos, badfn=None)
+        em = _buildkindpatsmatcher(
+            includematcher,
+            root,
+            kindpats,
+            ctx=ctx,
+            listsubrepos=listsubrepos,
+            badfn=None,
+        )
         m = differencematcher(m, em)
     return m
 
+
 def exact(files, badfn=None):
     return exactmatcher(files, badfn=badfn)
 
+
 def always(badfn=None):
     return alwaysmatcher(badfn)
 
+
 def never(badfn=None):
     return nevermatcher(badfn)
 
+
 def badmatch(match, badfn):
     """Make a copy of the given matcher, replacing its bad method with the given
     one.
@@ -259,6 +310,7 @@
     m.bad = badfn
     return m
 
+
 def _donormalize(patterns, default, root, cwd, auditor=None, warn=None):
     '''Convert 'kind:pat' from the patterns list to tuples with kind and
     normalized and rooted patterns and with listfiles expanded.'''
@@ -278,36 +330,41 @@
                 files = [f for f in files if f]
             except EnvironmentError:
                 raise error.Abort(_("unable to read file list (%s)") % pat)
-            for k, p, source in _donormalize(files, default, root, cwd,
-                                             auditor, warn):
+            for k, p, source in _donormalize(
+                files, default, root, cwd, auditor, warn
+            ):
                 kindpats.append((k, p, pat))
             continue
         elif kind == 'include':
             try:
                 fullpath = os.path.join(root, util.localpath(pat))
                 includepats = readpatternfile(fullpath, warn)
-                for k, p, source in _donormalize(includepats, default,
-                                                 root, cwd, auditor, warn):
+                for k, p, source in _donormalize(
+                    includepats, default, root, cwd, auditor, warn
+                ):
                     kindpats.append((k, p, source or pat))
             except error.Abort as inst:
                 raise error.Abort('%s: %s' % (pat, inst[0]))
             except IOError as inst:
                 if warn:
-                    warn(_("skipping unreadable pattern file '%s': %s\n") %
-                         (pat, stringutil.forcebytestr(inst.strerror)))
+                    warn(
+                        _("skipping unreadable pattern file '%s': %s\n")
+                        % (pat, stringutil.forcebytestr(inst.strerror))
+                    )
             continue
         # else: re or relre - which cannot be normalized
         kindpats.append((kind, pat, ''))
     return kindpats
 
+
 class basematcher(object):
-
     def __init__(self, badfn=None):
         if badfn is not None:
             self.bad = badfn
 
     def __call__(self, fn):
         return self.matchfn(fn)
+
     # Callbacks related to how the matcher is used by dirstate.walk.
     # Subscribers to these events must monkeypatch the matcher object.
     def bad(self, f, msg):
@@ -419,6 +476,7 @@
         optimizations will be difficult.'''
         return not self.always() and not self.isexact() and not self.prefix()
 
+
 class alwaysmatcher(basematcher):
     '''Matches everything.'''
 
@@ -440,6 +498,7 @@
     def __repr__(self):
         return r'<alwaysmatcher>'
 
+
 class nevermatcher(basematcher):
     '''Matches nothing.'''
 
@@ -466,6 +525,7 @@
     def __repr__(self):
         return r'<nevermatcher>'
 
+
 class predicatematcher(basematcher):
     """A matcher adapter for a simple boolean function"""
 
@@ -476,14 +536,18 @@
 
     @encoding.strmethod
     def __repr__(self):
-        s = (stringutil.buildrepr(self._predrepr)
-             or pycompat.byterepr(self.matchfn))
+        s = stringutil.buildrepr(self._predrepr) or pycompat.byterepr(
+            self.matchfn
+        )
         return '<predicatenmatcher pred=%s>' % s
 
+
 def normalizerootdir(dir, funcname):
     if dir == '.':
-        util.nouideprecwarn("match.%s() no longer accepts "
-                            "'.', use '' instead." % funcname, '5.1')
+        util.nouideprecwarn(
+            "match.%s() no longer accepts " "'.', use '' instead." % funcname,
+            '5.1',
+        )
         return ''
     return dir
 
@@ -536,10 +600,13 @@
         dir = normalizerootdir(dir, 'visitdir')
         if self._prefix and dir in self._fileset:
             return 'all'
-        return (dir in self._fileset or
-                dir in self._dirs or
-                any(parentdir in self._fileset
-                    for parentdir in util.finddirs(dir)))
+        return (
+            dir in self._fileset
+            or dir in self._dirs
+            or any(
+                parentdir in self._fileset for parentdir in util.finddirs(dir)
+            )
+        )
 
     def visitchildrenset(self, dir):
         ret = self.visitdir(dir)
@@ -555,7 +622,8 @@
 
     @encoding.strmethod
     def __repr__(self):
-        return ('<patternmatcher patterns=%r>' % pycompat.bytestr(self._pats))
+        return '<patternmatcher patterns=%r>' % pycompat.bytestr(self._pats)
+
 
 # This is basically a reimplementation of util.dirs that stores the children
 # instead of just a count of them, plus a small optional optimization to avoid
@@ -588,7 +656,7 @@
         oldpos = len(path)
         pos = path.rfind('/')
         while pos != -1:
-            yield path[:pos], path[pos + 1:oldpos]
+            yield path[:pos], path[pos + 1 : oldpos]
             oldpos = pos
             pos = path.rfind('/', 0, pos)
         yield '', path[:oldpos]
@@ -596,8 +664,8 @@
     def get(self, path):
         return self._dirs.get(path, set())
 
+
 class includematcher(basematcher):
-
     def __init__(self, root, kindpats, badfn=None):
         super(includematcher, self).__init__(badfn)
 
@@ -616,11 +684,12 @@
         dir = normalizerootdir(dir, 'visitdir')
         if self._prefix and dir in self._roots:
             return 'all'
-        return (dir in self._roots or
-                dir in self._dirs or
-                dir in self._parents or
-                any(parentdir in self._roots
-                    for parentdir in util.finddirs(dir)))
+        return (
+            dir in self._roots
+            or dir in self._dirs
+            or dir in self._parents
+            or any(parentdir in self._roots for parentdir in util.finddirs(dir))
+        )
 
     @propertycache
     def _allparentschildren(self):
@@ -631,19 +700,21 @@
         # if we asked for the children of 'foo', but had only added
         # self._parents, we wouldn't be able to respond ['bar'].
         return _dirchildren(
-                itertools.chain(self._dirs, self._roots, self._parents),
-                onlyinclude=self._parents)
+            itertools.chain(self._dirs, self._roots, self._parents),
+            onlyinclude=self._parents,
+        )
 
     def visitchildrenset(self, dir):
         if self._prefix and dir in self._roots:
             return 'all'
         # Note: this does *not* include the 'dir in self._parents' case from
         # visitdir, that's handled below.
-        if ('' in self._roots or
-            dir in self._roots or
-            dir in self._dirs or
-            any(parentdir in self._roots
-                for parentdir in util.finddirs(dir))):
+        if (
+            '' in self._roots
+            or dir in self._roots
+            or dir in self._dirs
+            or any(parentdir in self._roots for parentdir in util.finddirs(dir))
+        ):
             return 'this'
 
         if dir in self._parents:
@@ -652,7 +723,8 @@
 
     @encoding.strmethod
     def __repr__(self):
-        return ('<includematcher includes=%r>' % pycompat.bytestr(self._pats))
+        return '<includematcher includes=%r>' % pycompat.bytestr(self._pats)
+
 
 class exactmatcher(basematcher):
     r'''Matches the input files exactly. They are interpreted as paths, not
@@ -702,8 +774,7 @@
         candidates = self._fileset | self._dirs - {''}
         if dir != '':
             d = dir + '/'
-            candidates = set(c[len(d):] for c in candidates if
-                             c.startswith(d))
+            candidates = set(c[len(d) :] for c in candidates if c.startswith(d))
         # self._dirs includes all of the directories, recursively, so if
         # we're attempting to match foo/bar/baz.txt, it'll have '', 'foo',
         # 'foo/bar' in it. Thus we can safely ignore a candidate that has a
@@ -720,7 +791,8 @@
 
     @encoding.strmethod
     def __repr__(self):
-        return ('<exactmatcher files=%r>' % self._files)
+        return '<exactmatcher files=%r>' % self._files
+
 
 class differencematcher(basematcher):
     '''Composes two matchers by matching if the first matches and the second
@@ -729,6 +801,7 @@
     The second matcher's non-matching-attributes (bad, explicitdir,
     traversedir) are ignored.
     '''
+
     def __init__(self, m1, m2):
         super(differencematcher, self).__init__()
         self._m1 = m1
@@ -789,7 +862,8 @@
 
     @encoding.strmethod
     def __repr__(self):
-        return ('<differencematcher m1=%r, m2=%r>' % (self._m1, self._m2))
+        return '<differencematcher m1=%r, m2=%r>' % (self._m1, self._m2)
+
 
 def intersectmatchers(m1, m2):
     '''Composes two matchers by matching if both of them match.
@@ -812,6 +886,7 @@
         return m
     return intersectionmatcher(m1, m2)
 
+
 class intersectionmatcher(basematcher):
     def __init__(self, m1, m2):
         super(intersectionmatcher, self).__init__()
@@ -871,7 +946,8 @@
 
     @encoding.strmethod
     def __repr__(self):
-        return ('<intersectionmatcher m1=%r, m2=%r>' % (self._m1, self._m2))
+        return '<intersectionmatcher m1=%r, m2=%r>' % (self._m1, self._m2)
+
 
 class subdirmatcher(basematcher):
     """Adapt a matcher to work on a subdirectory only.
@@ -906,8 +982,11 @@
         self._matcher = matcher
         self._always = matcher.always()
 
-        self._files = [f[len(path) + 1:] for f in matcher._files
-                       if f.startswith(path + "/")]
+        self._files = [
+            f[len(path) + 1 :]
+            for f in matcher._files
+            if f.startswith(path + "/")
+        ]
 
         # If the parent repo had a path to this subrepo and the matcher is
         # a prefix matcher, this submatcher always matches.
@@ -948,8 +1027,11 @@
 
     @encoding.strmethod
     def __repr__(self):
-        return ('<subdirmatcher path=%r, matcher=%r>' %
-                (self._path, self._matcher))
+        return '<subdirmatcher path=%r, matcher=%r>' % (
+            self._path,
+            self._matcher,
+        )
+
 
 class prefixdirmatcher(basematcher):
     """Adapt a matcher to work on a parent directory.
@@ -999,7 +1081,7 @@
     def matchfn(self, f):
         if not f.startswith(self._pathprefix):
             return False
-        return self._matcher.matchfn(f[len(self._pathprefix):])
+        return self._matcher.matchfn(f[len(self._pathprefix) :])
 
     @propertycache
     def _pathdirs(self):
@@ -1009,14 +1091,14 @@
         if dir == self._path:
             return self._matcher.visitdir('')
         if dir.startswith(self._pathprefix):
-            return self._matcher.visitdir(dir[len(self._pathprefix):])
+            return self._matcher.visitdir(dir[len(self._pathprefix) :])
         return dir in self._pathdirs
 
     def visitchildrenset(self, dir):
         if dir == self._path:
             return self._matcher.visitchildrenset('')
         if dir.startswith(self._pathprefix):
-            return self._matcher.visitchildrenset(dir[len(self._pathprefix):])
+            return self._matcher.visitchildrenset(dir[len(self._pathprefix) :])
         if dir in self._pathdirs:
             return 'this'
         return set()
@@ -1029,8 +1111,11 @@
 
     @encoding.strmethod
     def __repr__(self):
-        return ('<prefixdirmatcher path=%r, matcher=%r>'
-                % (pycompat.bytestr(self._path), self._matcher))
+        return '<prefixdirmatcher path=%r, matcher=%r>' % (
+            pycompat.bytestr(self._path),
+            self._matcher,
+        )
+
 
 class unionmatcher(basematcher):
     """A matcher that is the union of several matchers.
@@ -1082,7 +1167,8 @@
 
     @encoding.strmethod
     def __repr__(self):
-        return ('<unionmatcher matchers=%r>' % self._matchers)
+        return '<unionmatcher matchers=%r>' % self._matchers
+
 
 def patkind(pattern, default=None):
     '''If pattern is 'kind:pat' with a known kind, return kind.
@@ -1099,6 +1185,7 @@
     '''
     return _patsplit(pattern, default)[0]
 
+
 def _patsplit(pattern, default):
     """Split a string into the optional pattern kind prefix and the actual
     pattern."""
@@ -1108,6 +1195,7 @@
             return kind, pat
     return default, pattern
 
+
 def _globre(pat):
     r'''Convert an extended glob string to a regexp string.
 
@@ -1135,10 +1223,12 @@
     res = ''
     group = 0
     escape = util.stringutil.regexbytesescapemap.get
+
     def peek():
-        return i < n and pat[i:i + 1]
+        return i < n and pat[i : i + 1]
+
     while i < n:
-        c = pat[i:i + 1]
+        c = pat[i : i + 1]
         i += 1
         if c not in '*?[{},\\':
             res += escape(c, c)
@@ -1156,14 +1246,14 @@
             res += '.'
         elif c == '[':
             j = i
-            if j < n and pat[j:j + 1] in '!]':
+            if j < n and pat[j : j + 1] in '!]':
                 j += 1
-            while j < n and pat[j:j + 1] != ']':
+            while j < n and pat[j : j + 1] != ']':
                 j += 1
             if j >= n:
                 res += '\\['
             else:
-                stuff = pat[i:j].replace('\\','\\\\')
+                stuff = pat[i:j].replace('\\', '\\\\')
                 i = j + 1
                 if stuff[0:1] == '!':
                     stuff = '^' + stuff[1:]
@@ -1189,6 +1279,7 @@
             res += escape(c, c)
     return res
 
+
 def _regex(kind, pat, globsuffix):
     '''Convert a (normalized) pattern of any kind into a
     regular expression.
@@ -1196,11 +1287,7 @@
 
     if rustmod is not None:
         try:
-            return rustmod.build_single_regex(
-                kind,
-                pat,
-                globsuffix
-            )
+            return rustmod.build_single_regex(kind, pat, globsuffix)
         except rustmod.PatternError:
             raise error.ProgrammingError(
                 'not a regex pattern: %s:%s' % (kind, pat)
@@ -1227,7 +1314,7 @@
         if globre.startswith('[^/]*'):
             # When pat has the form *XYZ (common), make the returned regex more
             # legible by returning the regex for **XYZ instead of **/*XYZ.
-            return '.*' + globre[len('[^/]*'):] + globsuffix
+            return '.*' + globre[len('[^/]*') :] + globsuffix
         return '(?:|.*/)' + globre + globsuffix
     if kind == 'relre':
         if pat.startswith('^'):
@@ -1237,6 +1324,7 @@
         return _globre(pat) + globsuffix
     raise error.ProgrammingError('not a regex pattern: %s:%s' % (kind, pat))
 
+
 def _buildmatch(kindpats, globsuffix, root):
     '''Return regexp string and a matcher function for kindpats.
     globsuffix is appended to the regexp of globs.'''
@@ -1245,6 +1333,7 @@
     subincludes, kindpats = _expandsubinclude(kindpats, root)
     if subincludes:
         submatchers = {}
+
         def matchsubinclude(f):
             for prefix, matcherargs in subincludes:
                 if f.startswith(prefix):
@@ -1253,15 +1342,17 @@
                         mf = match(*matcherargs)
                         submatchers[prefix] = mf
 
-                    if mf(f[len(prefix):]):
+                    if mf(f[len(prefix) :]):
                         return True
             return False
+
         matchfuncs.append(matchsubinclude)
 
     regex = ''
     if kindpats:
         if all(k == 'rootfilesin' for k, p, s in kindpats):
             dirs = {p for k, p, s in kindpats}
+
             def mf(f):
                 i = f.rfind('/')
                 if i >= 0:
@@ -1269,6 +1360,7 @@
                 else:
                     dir = '.'
                 return dir in dirs
+
             regex = b'rootfilesin: %s' % stringutil.pprint(list(sorted(dirs)))
             matchfuncs.append(mf)
         else:
@@ -1280,12 +1372,15 @@
     else:
         return regex, lambda f: any(mf(f) for mf in matchfuncs)
 
+
 MAX_RE_SIZE = 20000
 
+
 def _joinregexes(regexps):
     """gather multiple regular expressions into a single one"""
     return '|'.join(regexps)
 
+
 def _buildregexmatch(kindpats, globsuffix):
     """Build a match function from a list of kinds and kindpats,
     return regexp string and a matcher function.
@@ -1332,12 +1427,14 @@
                 _rematcher(_regex(k, p, globsuffix))
             except re.error:
                 if s:
-                    raise error.Abort(_("%s: invalid pattern (%s): %s") %
-                                      (s, k, p))
+                    raise error.Abort(
+                        _("%s: invalid pattern (%s): %s") % (s, k, p)
+                    )
                 else:
                     raise error.Abort(_("invalid pattern (%s): %s") % (k, p))
         raise error.Abort(_("invalid pattern"))
 
+
 def _patternrootsanddirs(kindpats):
     '''Returns roots and directories corresponding to each pattern.
 
@@ -1349,7 +1446,7 @@
     r = []
     d = []
     for kind, pat, source in kindpats:
-        if kind in ('glob', 'rootglob'): # find the non-glob prefix
+        if kind in ('glob', 'rootglob'):  # find the non-glob prefix
             root = []
             for p in pat.split('/'):
                 if '[' in p or '{' in p or '*' in p or '?' in p:
@@ -1364,15 +1461,17 @@
             if pat == '.':
                 pat = ''
             d.append(pat)
-        else: # relglob, re, relre
+        else:  # relglob, re, relre
             r.append('')
     return r, d
 
+
 def _roots(kindpats):
     '''Returns root directories to match recursively from the given patterns.'''
     roots, dirs = _patternrootsanddirs(kindpats)
     return roots
 
+
 def _rootsdirsandparents(kindpats):
     '''Returns roots and exact directories from patterns.
 
@@ -1416,6 +1515,7 @@
     # 'dirs' to also be in 'parents', consider removing them before returning.
     return r, d, p
 
+
 def _explicitfiles(kindpats):
     '''Returns the potential explicit filenames from the patterns.
 
@@ -1429,6 +1529,7 @@
     filable = [kp for kp in kindpats if kp[0] not in ('rootfilesin',)]
     return _roots(filable)
 
+
 def _prefix(kindpats):
     '''Whether all the patterns match a prefix (i.e. recursively)'''
     for kind, pat, source in kindpats:
@@ -1436,8 +1537,10 @@
             return False
     return True
 
+
 _commentre = None
 
+
 def readpatternfile(filepath, warn, sourceinfo=False):
     '''parse a pattern file, returning a list of
     patterns. These patterns should be given to compile()
@@ -1464,9 +1567,7 @@
 
     if rustmod is not None:
         result, warnings = rustmod.read_pattern_file(
-            filepath,
-            bool(warn),
-            sourceinfo,
+            filepath, bool(warn), sourceinfo,
         )
 
         for warning_params in warnings:
@@ -1496,7 +1597,7 @@
             # remove comments prefixed by an even number of escapes
             m = _commentre.search(line)
             if m:
-                line = line[:m.end(1)]
+                line = line[: m.end(1)]
             # fixup properly escaped comments that survived the above
             line = line.replace("\\#", "#")
         line = line.rstrip()
@@ -1509,19 +1610,20 @@
                 syntax = syntaxes[s]
             except KeyError:
                 if warn:
-                    warn(_("%s: ignoring invalid syntax '%s'\n") %
-                         (filepath, s))
+                    warn(
+                        _("%s: ignoring invalid syntax '%s'\n") % (filepath, s)
+                    )
             continue
 
         linesyntax = syntax
         for s, rels in syntaxes.iteritems():
             if line.startswith(rels):
                 linesyntax = rels
-                line = line[len(rels):]
+                line = line[len(rels) :]
                 break
-            elif line.startswith(s+':'):
+            elif line.startswith(s + ':'):
                 linesyntax = rels
-                line = line[len(s) + 1:]
+                line = line[len(s) + 1 :]
                 break
         if sourceinfo:
             patterns.append((linesyntax + line, lineno, line))