github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/third_party/stdlib/glob.py (about)

     1  """Filename globbing utility."""
     2  
     3  import sys
     4  import os
     5  import re
     6  import fnmatch
     7  
     8  try:
     9      _unicode = unicode
    10  except NameError:
    11      # If Python is built without Unicode support, the unicode type
    12      # will not exist. Fake one.
    13      class _unicode(object):
    14          pass
    15  
    16  __all__ = ["glob", "iglob"]
    17  
    18  def glob(pathname):
    19      """Return a list of paths matching a pathname pattern.
    20  
    21      The pattern may contain simple shell-style wildcards a la
    22      fnmatch. However, unlike fnmatch, filenames starting with a
    23      dot are special cases that are not matched by '*' and '?'
    24      patterns.
    25  
    26      """
    27      return list(iglob(pathname))
    28  
    29  def iglob(pathname):
    30      """Return an iterator which yields the paths matching a pathname pattern.
    31  
    32      The pattern may contain simple shell-style wildcards a la
    33      fnmatch. However, unlike fnmatch, filenames starting with a
    34      dot are special cases that are not matched by '*' and '?'
    35      patterns.
    36  
    37      """
    38      dirname, basename = os.path.split(pathname)
    39      if not has_magic(pathname):
    40          if basename:
    41              if os.path.lexists(pathname):
    42                  yield pathname
    43          else:
    44              # Patterns ending with a slash should match only directories
    45              if os.path.isdir(dirname):
    46                  yield pathname
    47          return
    48      if not dirname:
    49          for name in glob1(os.curdir, basename):
    50              yield name
    51          return
    52      # `os.path.split()` returns the argument itself as a dirname if it is a
    53      # drive or UNC path.  Prevent an infinite recursion if a drive or UNC path
    54      # contains magic characters (i.e. r'\\?\C:').
    55      if dirname != pathname and has_magic(dirname):
    56          dirs = iglob(dirname)
    57      else:
    58          dirs = [dirname]
    59      if has_magic(basename):
    60          glob_in_dir = glob1
    61      else:
    62          glob_in_dir = glob0
    63      for dirname in dirs:
    64          for name in glob_in_dir(dirname, basename):
    65              yield os.path.join(dirname, name)
    66  
    67  # These 2 helper functions non-recursively glob inside a literal directory.
    68  # They return a list of basenames. `glob1` accepts a pattern while `glob0`
    69  # takes a literal basename (so it only has to check for its existence).
    70  
    71  def glob1(dirname, pattern):
    72      if not dirname:
    73          dirname = os.curdir
    74      if isinstance(pattern, _unicode) and not isinstance(dirname, unicode):
    75          dirname = unicode(dirname, sys.getfilesystemencoding() or
    76                                     sys.getdefaultencoding())
    77      try:
    78          names = os.listdir(dirname)
    79      except os.error:
    80          return []
    81      if pattern[0] != '.':
    82          # names = filter(lambda x: x[0] != '.', names)
    83          names = [x for x in names if x[0] != '.']
    84      return fnmatch.filter(names, pattern)
    85  
    86  def glob0(dirname, basename):
    87      if basename == '':
    88          # `os.path.split()` returns an empty basename for paths ending with a
    89          # directory separator.  'q*x/' should match only directories.
    90          if os.path.isdir(dirname):
    91              return [basename]
    92      else:
    93          if os.path.lexists(os.path.join(dirname, basename)):
    94              return [basename]
    95      return []
    96  
    97  
    98  magic_check = re.compile('[*?[]')
    99  
   100  def has_magic(s):
   101      return magic_check.search(s) is not None