blob: cba8c7c60e217e7937c4d6bb4ee23e5c34764f4e [file] [log] [blame]
Fred Drake99e87f92001-07-23 16:08:36 +00001import glob
2import os
Johannes Gijsbersa3beee12005-01-08 13:28:54 +00003import shutil
Antoine Pitrou3d068b22012-12-16 13:49:37 +01004import sys
Hynek Schlawacke26568f2012-12-27 10:10:11 +01005import unittest
6
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +03007from test.support import (TESTFN, skip_unless_symlink,
Serhiy Storchakaa1b16ba2014-09-11 14:33:02 +03008 can_symlink, create_empty_file, change_cwd)
Fred Drake99e87f92001-07-23 16:08:36 +00009
Hynek Schlawackdec59ec2012-12-16 12:39:11 +010010
Fred Drake99e87f92001-07-23 16:08:36 +000011class GlobTests(unittest.TestCase):
12
13 def norm(self, *parts):
14 return os.path.normpath(os.path.join(self.tempdir, *parts))
15
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +030016 def joins(self, *tuples):
17 return [os.path.join(self.tempdir, *parts) for parts in tuples]
18
Fred Drake99e87f92001-07-23 16:08:36 +000019 def mktemp(self, *parts):
Johannes Gijsbersa3beee12005-01-08 13:28:54 +000020 filename = self.norm(*parts)
21 base, file = os.path.split(filename)
22 if not os.path.exists(base):
23 os.makedirs(base)
Victor Stinnerbf816222011-06-30 23:25:47 +020024 create_empty_file(filename)
Fred Drake99e87f92001-07-23 16:08:36 +000025
26 def setUp(self):
Hynek Schlawackdec59ec2012-12-16 12:39:11 +010027 self.tempdir = TESTFN + "_dir"
Fred Drake99e87f92001-07-23 16:08:36 +000028 self.mktemp('a', 'D')
29 self.mktemp('aab', 'F')
Hynek Schlawackdec59ec2012-12-16 12:39:11 +010030 self.mktemp('.aa', 'G')
31 self.mktemp('.bb', 'H')
Fred Drake99e87f92001-07-23 16:08:36 +000032 self.mktemp('aaa', 'zzzF')
33 self.mktemp('ZZZ')
Serhiy Storchaka735b7902015-11-09 23:12:07 +020034 self.mktemp('EF')
Fred Drake99e87f92001-07-23 16:08:36 +000035 self.mktemp('a', 'bcd', 'EF')
36 self.mktemp('a', 'bcd', 'efg', 'ha')
Brian Curtin3b4499c2010-12-28 14:31:47 +000037 if can_symlink():
Johannes Gijsbersae882f72004-08-30 10:19:56 +000038 os.symlink(self.norm('broken'), self.norm('sym1'))
Hynek Schlawacke26568f2012-12-27 10:10:11 +010039 os.symlink('broken', self.norm('sym2'))
40 os.symlink(os.path.join('a', 'bcd'), self.norm('sym3'))
Fred Drake99e87f92001-07-23 16:08:36 +000041
42 def tearDown(self):
Johannes Gijsbersa3beee12005-01-08 13:28:54 +000043 shutil.rmtree(self.tempdir)
Fred Drake99e87f92001-07-23 16:08:36 +000044
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +030045 def glob(self, *parts, **kwargs):
Fred Drake99e87f92001-07-23 16:08:36 +000046 if len(parts) == 1:
47 pattern = parts[0]
48 else:
49 pattern = os.path.join(*parts)
50 p = os.path.join(self.tempdir, pattern)
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +030051 res = glob.glob(p, **kwargs)
Gregory P. Smith39414992018-01-17 14:57:57 -080052 self.assertCountEqual(glob.iglob(p, **kwargs), res)
Hynek Schlawacke26568f2012-12-27 10:10:11 +010053 bres = [os.fsencode(x) for x in res]
Gregory P. Smith39414992018-01-17 14:57:57 -080054 self.assertCountEqual(glob.glob(os.fsencode(p), **kwargs), bres)
55 self.assertCountEqual(glob.iglob(os.fsencode(p), **kwargs), bres)
Johannes Gijsbers836f5432005-01-08 13:13:19 +000056 return res
Fred Drake99e87f92001-07-23 16:08:36 +000057
58 def assertSequencesEqual_noorder(self, l1, l2):
Hynek Schlawacke26568f2012-12-27 10:10:11 +010059 l1 = list(l1)
60 l2 = list(l2)
Raymond Hettingera690a992003-11-16 16:17:49 +000061 self.assertEqual(set(l1), set(l2))
Hynek Schlawacke26568f2012-12-27 10:10:11 +010062 self.assertEqual(sorted(l1), sorted(l2))
Fred Drake99e87f92001-07-23 16:08:36 +000063
64 def test_glob_literal(self):
65 eq = self.assertSequencesEqual_noorder
Fred Drake99e87f92001-07-23 16:08:36 +000066 eq(self.glob('a'), [self.norm('a')])
67 eq(self.glob('a', 'D'), [self.norm('a', 'D')])
68 eq(self.glob('aab'), [self.norm('aab')])
69 eq(self.glob('zymurgy'), [])
70
Hynek Schlawacke26568f2012-12-27 10:10:11 +010071 res = glob.glob('*')
72 self.assertEqual({type(r) for r in res}, {str})
73 res = glob.glob(os.path.join(os.curdir, '*'))
74 self.assertEqual({type(r) for r in res}, {str})
75
76 res = glob.glob(b'*')
77 self.assertEqual({type(r) for r in res}, {bytes})
78 res = glob.glob(os.path.join(os.fsencode(os.curdir), b'*'))
79 self.assertEqual({type(r) for r in res}, {bytes})
Guido van Rossumd8faa362007-04-27 19:54:29 +000080
Fred Drake99e87f92001-07-23 16:08:36 +000081 def test_glob_one_directory(self):
82 eq = self.assertSequencesEqual_noorder
Fred Drake99e87f92001-07-23 16:08:36 +000083 eq(self.glob('a*'), map(self.norm, ['a', 'aab', 'aaa']))
84 eq(self.glob('*a'), map(self.norm, ['a', 'aaa']))
Hynek Schlawackdec59ec2012-12-16 12:39:11 +010085 eq(self.glob('.*'), map(self.norm, ['.aa', '.bb']))
86 eq(self.glob('?aa'), map(self.norm, ['aaa']))
Fred Drake99e87f92001-07-23 16:08:36 +000087 eq(self.glob('aa?'), map(self.norm, ['aaa', 'aab']))
88 eq(self.glob('aa[ab]'), map(self.norm, ['aaa', 'aab']))
89 eq(self.glob('*q'), [])
90
91 def test_glob_nested_directory(self):
92 eq = self.assertSequencesEqual_noorder
Fred Drake99e87f92001-07-23 16:08:36 +000093 if os.path.normcase("abCD") == "abCD":
94 # case-sensitive filesystem
95 eq(self.glob('a', 'bcd', 'E*'), [self.norm('a', 'bcd', 'EF')])
96 else:
97 # case insensitive filesystem
98 eq(self.glob('a', 'bcd', 'E*'), [self.norm('a', 'bcd', 'EF'),
99 self.norm('a', 'bcd', 'efg')])
100 eq(self.glob('a', 'bcd', '*g'), [self.norm('a', 'bcd', 'efg')])
101
102 def test_glob_directory_names(self):
103 eq = self.assertSequencesEqual_noorder
Fred Drake99e87f92001-07-23 16:08:36 +0000104 eq(self.glob('*', 'D'), [self.norm('a', 'D')])
105 eq(self.glob('*', '*a'), [])
106 eq(self.glob('a', '*', '*', '*a'),
107 [self.norm('a', 'bcd', 'efg', 'ha')])
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100108 eq(self.glob('?a?', '*F'), [self.norm('aaa', 'zzzF'),
109 self.norm('aab', 'F')])
Fred Drake99e87f92001-07-23 16:08:36 +0000110
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000111 def test_glob_directory_with_trailing_slash(self):
Antoine Pitrou54615582012-12-16 16:03:01 +0100112 # Patterns ending with a slash shouldn't match non-dirs
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100113 res = glob.glob(self.norm('Z*Z') + os.sep)
Antoine Pitrou54615582012-12-16 16:03:01 +0100114 self.assertEqual(res, [])
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100115 res = glob.glob(self.norm('ZZZ') + os.sep)
Antoine Pitrou54615582012-12-16 16:03:01 +0100116 self.assertEqual(res, [])
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100117 # When there is a wildcard pattern which ends with os.sep, glob()
Antoine Pitrou54615582012-12-16 16:03:01 +0100118 # doesn't blow up.
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100119 res = glob.glob(self.norm('aa*') + os.sep)
Antoine Pitrou54615582012-12-16 16:03:01 +0100120 self.assertEqual(len(res), 2)
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100121 # either of these results is reasonable
Antoine Pitrou54615582012-12-16 16:03:01 +0100122 self.assertIn(set(res), [
123 {self.norm('aaa'), self.norm('aab')},
124 {self.norm('aaa') + os.sep, self.norm('aab') + os.sep},
125 ])
126
127 def test_glob_bytes_directory_with_trailing_slash(self):
128 # Same as test_glob_directory_with_trailing_slash, but with a
129 # bytes argument.
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100130 res = glob.glob(os.fsencode(self.norm('Z*Z') + os.sep))
Antoine Pitrou54615582012-12-16 16:03:01 +0100131 self.assertEqual(res, [])
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100132 res = glob.glob(os.fsencode(self.norm('ZZZ') + os.sep))
Antoine Pitrou54615582012-12-16 16:03:01 +0100133 self.assertEqual(res, [])
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100134 res = glob.glob(os.fsencode(self.norm('aa*') + os.sep))
Antoine Pitrou54615582012-12-16 16:03:01 +0100135 self.assertEqual(len(res), 2)
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100136 # either of these results is reasonable
137 self.assertIn(set(res), [
138 {os.fsencode(self.norm('aaa')),
139 os.fsencode(self.norm('aab'))},
140 {os.fsencode(self.norm('aaa') + os.sep),
141 os.fsencode(self.norm('aab') + os.sep)},
Antoine Pitrou54615582012-12-16 16:03:01 +0100142 ])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000143
Brian Curtin3b4499c2010-12-28 14:31:47 +0000144 @skip_unless_symlink
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100145 def test_glob_symlinks(self):
146 eq = self.assertSequencesEqual_noorder
147 eq(self.glob('sym3'), [self.norm('sym3')])
148 eq(self.glob('sym3', '*'), [self.norm('sym3', 'EF'),
149 self.norm('sym3', 'efg')])
150 self.assertIn(self.glob('sym3' + os.sep),
151 [[self.norm('sym3')], [self.norm('sym3') + os.sep]])
152 eq(self.glob('*', '*F'),
153 [self.norm('aaa', 'zzzF'),
154 self.norm('aab', 'F'), self.norm('sym3', 'EF')])
155
156 @skip_unless_symlink
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000157 def test_glob_broken_symlinks(self):
Brian Curtind40e6f72010-07-08 21:39:08 +0000158 eq = self.assertSequencesEqual_noorder
Hynek Schlawacke26568f2012-12-27 10:10:11 +0100159 eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2'),
160 self.norm('sym3')])
Brian Curtind40e6f72010-07-08 21:39:08 +0000161 eq(self.glob('sym1'), [self.norm('sym1')])
162 eq(self.glob('sym2'), [self.norm('sym2')])
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000163
Antoine Pitrou3d068b22012-12-16 13:49:37 +0100164 @unittest.skipUnless(sys.platform == "win32", "Win32 specific test")
165 def test_glob_magic_in_drive(self):
166 eq = self.assertSequencesEqual_noorder
167 eq(glob.glob('*:'), [])
168 eq(glob.glob(b'*:'), [])
169 eq(glob.glob('?:'), [])
170 eq(glob.glob(b'?:'), [])
171 eq(glob.glob('\\\\?\\c:\\'), ['\\\\?\\c:\\'])
172 eq(glob.glob(b'\\\\?\\c:\\'), [b'\\\\?\\c:\\'])
173 eq(glob.glob('\\\\*\\*\\'), [])
174 eq(glob.glob(b'\\\\*\\*\\'), [])
175
Serhiy Storchakafd32fff2013-11-18 13:06:43 +0200176 def check_escape(self, arg, expected):
177 self.assertEqual(glob.escape(arg), expected)
178 self.assertEqual(glob.escape(os.fsencode(arg)), os.fsencode(expected))
179
180 def test_escape(self):
181 check = self.check_escape
182 check('abc', 'abc')
183 check('[', '[[]')
184 check('?', '[?]')
185 check('*', '[*]')
186 check('[[_/*?*/_]]', '[[][[]_/[*][?][*]/_]]')
187 check('/[[_/*?*/_]]/', '/[[][[]_/[*][?][*]/_]]/')
188
189 @unittest.skipUnless(sys.platform == "win32", "Win32 specific test")
190 def test_escape_windows(self):
191 check = self.check_escape
192 check('?:?', '?:[?]')
193 check('*:*', '*:[*]')
194 check(r'\\?\c:\?', r'\\?\c:\[?]')
195 check(r'\\*\*\*', r'\\*\*\[*]')
196 check('//?/c:/?', '//?/c:/[?]')
197 check('//*/*/*', '//*/*/[*]')
Fred Drake2e2be372001-09-20 21:33:42 +0000198
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300199 def rglob(self, *parts, **kwargs):
200 return self.glob(*parts, recursive=True, **kwargs)
201
202 def test_recursive_glob(self):
203 eq = self.assertSequencesEqual_noorder
Serhiy Storchaka735b7902015-11-09 23:12:07 +0200204 full = [('EF',), ('ZZZ',),
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300205 ('a',), ('a', 'D'),
206 ('a', 'bcd'),
207 ('a', 'bcd', 'EF'),
208 ('a', 'bcd', 'efg'),
209 ('a', 'bcd', 'efg', 'ha'),
210 ('aaa',), ('aaa', 'zzzF'),
211 ('aab',), ('aab', 'F'),
212 ]
213 if can_symlink():
214 full += [('sym1',), ('sym2',),
215 ('sym3',),
216 ('sym3', 'EF'),
217 ('sym3', 'efg'),
218 ('sym3', 'efg', 'ha'),
219 ]
220 eq(self.rglob('**'), self.joins(('',), *full))
Serhiy Storchaka735b7902015-11-09 23:12:07 +0200221 eq(self.rglob(os.curdir, '**'),
222 self.joins((os.curdir, ''), *((os.curdir,) + i for i in full)))
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300223 dirs = [('a', ''), ('a', 'bcd', ''), ('a', 'bcd', 'efg', ''),
224 ('aaa', ''), ('aab', '')]
225 if can_symlink():
226 dirs += [('sym3', ''), ('sym3', 'efg', '')]
227 eq(self.rglob('**', ''), self.joins(('',), *dirs))
228
229 eq(self.rglob('a', '**'), self.joins(
230 ('a', ''), ('a', 'D'), ('a', 'bcd'), ('a', 'bcd', 'EF'),
231 ('a', 'bcd', 'efg'), ('a', 'bcd', 'efg', 'ha')))
232 eq(self.rglob('a**'), self.joins(('a',), ('aaa',), ('aab',)))
Serhiy Storchaka735b7902015-11-09 23:12:07 +0200233 expect = [('a', 'bcd', 'EF'), ('EF',)]
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300234 if can_symlink():
235 expect += [('sym3', 'EF')]
236 eq(self.rglob('**', 'EF'), self.joins(*expect))
Serhiy Storchaka735b7902015-11-09 23:12:07 +0200237 expect = [('a', 'bcd', 'EF'), ('aaa', 'zzzF'), ('aab', 'F'), ('EF',)]
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300238 if can_symlink():
239 expect += [('sym3', 'EF')]
240 eq(self.rglob('**', '*F'), self.joins(*expect))
241 eq(self.rglob('**', '*F', ''), [])
242 eq(self.rglob('**', 'bcd', '*'), self.joins(
243 ('a', 'bcd', 'EF'), ('a', 'bcd', 'efg')))
244 eq(self.rglob('a', '**', 'bcd'), self.joins(('a', 'bcd')))
245
Serhiy Storchaka5fbadb62015-09-06 14:14:49 +0300246 with change_cwd(self.tempdir):
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300247 join = os.path.join
248 eq(glob.glob('**', recursive=True), [join(*i) for i in full])
249 eq(glob.glob(join('**', ''), recursive=True),
250 [join(*i) for i in dirs])
Serhiy Storchaka735b7902015-11-09 23:12:07 +0200251 eq(glob.glob(join('**', '*'), recursive=True),
252 [join(*i) for i in full])
253 eq(glob.glob(join(os.curdir, '**'), recursive=True),
254 [join(os.curdir, '')] + [join(os.curdir, *i) for i in full])
255 eq(glob.glob(join(os.curdir, '**', ''), recursive=True),
256 [join(os.curdir, '')] + [join(os.curdir, *i) for i in dirs])
257 eq(glob.glob(join(os.curdir, '**', '*'), recursive=True),
258 [join(os.curdir, *i) for i in full])
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300259 eq(glob.glob(join('**','zz*F'), recursive=True),
260 [join('aaa', 'zzzF')])
261 eq(glob.glob('**zz*F', recursive=True), [])
Serhiy Storchaka735b7902015-11-09 23:12:07 +0200262 expect = [join('a', 'bcd', 'EF'), 'EF']
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300263 if can_symlink():
264 expect += [join('sym3', 'EF')]
265 eq(glob.glob(join('**', 'EF'), recursive=True), expect)
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300266
Miss Islington (bot)98a4a712019-09-12 08:07:47 -0700267 def test_glob_many_open_files(self):
268 depth = 30
269 base = os.path.join(self.tempdir, 'deep')
270 p = os.path.join(base, *(['d']*depth))
271 os.makedirs(p)
272 pattern = os.path.join(base, *(['*']*depth))
273 iters = [glob.iglob(pattern, recursive=True) for j in range(100)]
274 for it in iters:
275 self.assertEqual(next(it), p)
276 pattern = os.path.join(base, '**', 'd')
277 iters = [glob.iglob(pattern, recursive=True) for j in range(100)]
278 p = base
279 for i in range(depth):
280 p = os.path.join(p, 'd')
281 for it in iters:
282 self.assertEqual(next(it), p)
283
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300284
285@skip_unless_symlink
286class SymlinkLoopGlobTests(unittest.TestCase):
287
288 def test_selflink(self):
289 tempdir = TESTFN + "_dir"
290 os.makedirs(tempdir)
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300291 self.addCleanup(shutil.rmtree, tempdir)
Serhiy Storchakaa1b16ba2014-09-11 14:33:02 +0300292 with change_cwd(tempdir):
293 os.makedirs('dir')
294 create_empty_file(os.path.join('dir', 'file'))
295 os.symlink(os.curdir, os.path.join('dir', 'link'))
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300296
Serhiy Storchakaa1b16ba2014-09-11 14:33:02 +0300297 results = glob.glob('**', recursive=True)
298 self.assertEqual(len(results), len(set(results)))
299 results = set(results)
300 depth = 0
301 while results:
302 path = os.path.join(*(['dir'] + ['link'] * depth))
303 self.assertIn(path, results)
304 results.remove(path)
305 if not results:
306 break
307 path = os.path.join(path, 'file')
308 self.assertIn(path, results)
309 results.remove(path)
310 depth += 1
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300311
Serhiy Storchakaa1b16ba2014-09-11 14:33:02 +0300312 results = glob.glob(os.path.join('**', 'file'), recursive=True)
313 self.assertEqual(len(results), len(set(results)))
314 results = set(results)
315 depth = 0
316 while results:
317 path = os.path.join(*(['dir'] + ['link'] * depth + ['file']))
318 self.assertIn(path, results)
319 results.remove(path)
320 depth += 1
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300321
Serhiy Storchakaa1b16ba2014-09-11 14:33:02 +0300322 results = glob.glob(os.path.join('**', ''), recursive=True)
323 self.assertEqual(len(results), len(set(results)))
324 results = set(results)
325 depth = 0
326 while results:
327 path = os.path.join(*(['dir'] + ['link'] * depth + ['']))
328 self.assertIn(path, results)
329 results.remove(path)
330 depth += 1
Fred Drake2e2be372001-09-20 21:33:42 +0000331
332
333if __name__ == "__main__":
Serhiy Storchakac2edcdd2014-09-11 12:17:37 +0300334 unittest.main()