annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/site-packages/setuptools/glob.py @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
rev   line source
jpayne@69 1 """
jpayne@69 2 Filename globbing utility. Mostly a copy of `glob` from Python 3.5.
jpayne@69 3
jpayne@69 4 Changes include:
jpayne@69 5 * `yield from` and PEP3102 `*` removed.
jpayne@69 6 * Hidden files are not ignored.
jpayne@69 7 """
jpayne@69 8
jpayne@69 9 import fnmatch
jpayne@69 10 import os
jpayne@69 11 import re
jpayne@69 12
jpayne@69 13 __all__ = ["glob", "iglob", "escape"]
jpayne@69 14
jpayne@69 15
jpayne@69 16 def glob(pathname, recursive: bool = False):
jpayne@69 17 """Return a list of paths matching a pathname pattern.
jpayne@69 18
jpayne@69 19 The pattern may contain simple shell-style wildcards a la
jpayne@69 20 fnmatch. However, unlike fnmatch, filenames starting with a
jpayne@69 21 dot are special cases that are not matched by '*' and '?'
jpayne@69 22 patterns.
jpayne@69 23
jpayne@69 24 If recursive is true, the pattern '**' will match any files and
jpayne@69 25 zero or more directories and subdirectories.
jpayne@69 26 """
jpayne@69 27 return list(iglob(pathname, recursive=recursive))
jpayne@69 28
jpayne@69 29
jpayne@69 30 def iglob(pathname, recursive: bool = False):
jpayne@69 31 """Return an iterator which yields the paths matching a pathname pattern.
jpayne@69 32
jpayne@69 33 The pattern may contain simple shell-style wildcards a la
jpayne@69 34 fnmatch. However, unlike fnmatch, filenames starting with a
jpayne@69 35 dot are special cases that are not matched by '*' and '?'
jpayne@69 36 patterns.
jpayne@69 37
jpayne@69 38 If recursive is true, the pattern '**' will match any files and
jpayne@69 39 zero or more directories and subdirectories.
jpayne@69 40 """
jpayne@69 41 it = _iglob(pathname, recursive)
jpayne@69 42 if recursive and _isrecursive(pathname):
jpayne@69 43 s = next(it) # skip empty string
jpayne@69 44 assert not s
jpayne@69 45 return it
jpayne@69 46
jpayne@69 47
jpayne@69 48 def _iglob(pathname, recursive):
jpayne@69 49 dirname, basename = os.path.split(pathname)
jpayne@69 50 glob_in_dir = glob2 if recursive and _isrecursive(basename) else glob1
jpayne@69 51
jpayne@69 52 if not has_magic(pathname):
jpayne@69 53 if basename:
jpayne@69 54 if os.path.lexists(pathname):
jpayne@69 55 yield pathname
jpayne@69 56 else:
jpayne@69 57 # Patterns ending with a slash should match only directories
jpayne@69 58 if os.path.isdir(dirname):
jpayne@69 59 yield pathname
jpayne@69 60 return
jpayne@69 61
jpayne@69 62 if not dirname:
jpayne@69 63 yield from glob_in_dir(dirname, basename)
jpayne@69 64 return
jpayne@69 65 # `os.path.split()` returns the argument itself as a dirname if it is a
jpayne@69 66 # drive or UNC path. Prevent an infinite recursion if a drive or UNC path
jpayne@69 67 # contains magic characters (i.e. r'\\?\C:').
jpayne@69 68 if dirname != pathname and has_magic(dirname):
jpayne@69 69 dirs = _iglob(dirname, recursive)
jpayne@69 70 else:
jpayne@69 71 dirs = [dirname]
jpayne@69 72 if not has_magic(basename):
jpayne@69 73 glob_in_dir = glob0
jpayne@69 74 for dirname in dirs:
jpayne@69 75 for name in glob_in_dir(dirname, basename):
jpayne@69 76 yield os.path.join(dirname, name)
jpayne@69 77
jpayne@69 78
jpayne@69 79 # These 2 helper functions non-recursively glob inside a literal directory.
jpayne@69 80 # They return a list of basenames. `glob1` accepts a pattern while `glob0`
jpayne@69 81 # takes a literal basename (so it only has to check for its existence).
jpayne@69 82
jpayne@69 83
jpayne@69 84 def glob1(dirname, pattern):
jpayne@69 85 if not dirname:
jpayne@69 86 if isinstance(pattern, bytes):
jpayne@69 87 dirname = os.curdir.encode('ASCII')
jpayne@69 88 else:
jpayne@69 89 dirname = os.curdir
jpayne@69 90 try:
jpayne@69 91 names = os.listdir(dirname)
jpayne@69 92 except OSError:
jpayne@69 93 return []
jpayne@69 94 return fnmatch.filter(names, pattern)
jpayne@69 95
jpayne@69 96
jpayne@69 97 def glob0(dirname, basename):
jpayne@69 98 if not basename:
jpayne@69 99 # `os.path.split()` returns an empty basename for paths ending with a
jpayne@69 100 # directory separator. 'q*x/' should match only directories.
jpayne@69 101 if os.path.isdir(dirname):
jpayne@69 102 return [basename]
jpayne@69 103 else:
jpayne@69 104 if os.path.lexists(os.path.join(dirname, basename)):
jpayne@69 105 return [basename]
jpayne@69 106 return []
jpayne@69 107
jpayne@69 108
jpayne@69 109 # This helper function recursively yields relative pathnames inside a literal
jpayne@69 110 # directory.
jpayne@69 111
jpayne@69 112
jpayne@69 113 def glob2(dirname, pattern):
jpayne@69 114 assert _isrecursive(pattern)
jpayne@69 115 yield pattern[:0]
jpayne@69 116 yield from _rlistdir(dirname)
jpayne@69 117
jpayne@69 118
jpayne@69 119 # Recursively yields relative pathnames inside a literal directory.
jpayne@69 120 def _rlistdir(dirname):
jpayne@69 121 if not dirname:
jpayne@69 122 if isinstance(dirname, bytes):
jpayne@69 123 dirname = os.curdir.encode('ASCII')
jpayne@69 124 else:
jpayne@69 125 dirname = os.curdir
jpayne@69 126 try:
jpayne@69 127 names = os.listdir(dirname)
jpayne@69 128 except OSError:
jpayne@69 129 return
jpayne@69 130 for x in names:
jpayne@69 131 yield x
jpayne@69 132 path = os.path.join(dirname, x) if dirname else x
jpayne@69 133 for y in _rlistdir(path):
jpayne@69 134 yield os.path.join(x, y)
jpayne@69 135
jpayne@69 136
jpayne@69 137 magic_check = re.compile('([*?[])')
jpayne@69 138 magic_check_bytes = re.compile(b'([*?[])')
jpayne@69 139
jpayne@69 140
jpayne@69 141 def has_magic(s):
jpayne@69 142 if isinstance(s, bytes):
jpayne@69 143 match = magic_check_bytes.search(s)
jpayne@69 144 else:
jpayne@69 145 match = magic_check.search(s)
jpayne@69 146 return match is not None
jpayne@69 147
jpayne@69 148
jpayne@69 149 def _isrecursive(pattern):
jpayne@69 150 if isinstance(pattern, bytes):
jpayne@69 151 return pattern == b'**'
jpayne@69 152 else:
jpayne@69 153 return pattern == '**'
jpayne@69 154
jpayne@69 155
jpayne@69 156 def escape(pathname):
jpayne@69 157 """Escape all special characters."""
jpayne@69 158 # Escaping is done by wrapping any of "*?[" between square brackets.
jpayne@69 159 # Metacharacters do not work in the drive part and shouldn't be escaped.
jpayne@69 160 drive, pathname = os.path.splitdrive(pathname)
jpayne@69 161 if isinstance(pathname, bytes):
jpayne@69 162 pathname = magic_check_bytes.sub(rb'[\1]', pathname)
jpayne@69 163 else:
jpayne@69 164 pathname = magic_check.sub(r'[\1]', pathname)
jpayne@69 165 return drive + pathname