/sphinx/util/matching.py
Python | 80 lines | 59 code | 3 blank | 18 comment | 18 complexity | 0091ef15b8fa1be78b9cb142f87c4a1f MD5 | raw file
Possible License(s): BSD-2-Clause
- # -*- coding: utf-8 -*-
- """
- sphinx.util.matching
- ~~~~~~~~~~~~~~~~~~~~
- Pattern-matching utility functions for Sphinx.
- :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
- :license: BSD, see LICENSE for details.
- """
- import re
- def _translate_pattern(pat):
- """Translate a shell-style glob pattern to a regular expression.
- Adapted from the fnmatch module, but enhanced so that single stars don't
- match slashes.
- """
- i, n = 0, len(pat)
- res = ''
- while i < n:
- c = pat[i]
- i += 1
- if c == '*':
- if i < n and pat[i] == '*':
- # double star matches slashes too
- i += 1
- res = res + '.*'
- else:
- # single star doesn't match slashes
- res = res + '[^/]*'
- elif c == '?':
- # question mark doesn't match slashes too
- res = res + '[^/]'
- elif c == '[':
- j = i
- if j < n and pat[j] == '!':
- j += 1
- if j < n and pat[j] == ']':
- j += 1
- while j < n and pat[j] != ']':
- j += 1
- if j >= n:
- res = res + '\\['
- else:
- stuff = pat[i:j].replace('\\', '\\\\')
- i = j + 1
- if stuff[0] == '!':
- # negative pattern mustn't match slashes too
- stuff = '^/' + stuff[1:]
- elif stuff[0] == '^':
- stuff = '\\' + stuff
- res = '%s[%s]' % (res, stuff)
- else:
- res += re.escape(c)
- return res + '$'
- def compile_matchers(patterns):
- return [re.compile(_translate_pattern(pat)).match for pat in patterns]
- _pat_cache = {}
- def patmatch(name, pat):
- """Return if name matches pat. Adapted from fnmatch module."""
- if pat not in _pat_cache:
- _pat_cache[pat] = re.compile(_translate_pattern(pat))
- return _pat_cache[pat].match(name)
- def patfilter(names, pat):
- """Return the subset of the list NAMES that match PAT.
- Adapted from fnmatch module.
- """
- if pat not in _pat_cache:
- _pat_cache[pat] = re.compile(_translate_pattern(pat))
- match = _pat_cache[pat].match
- return list(filter(match, names))