test_glob.py 12.4 KB
Newer Older
1 2
import glob
import os
3
import shutil
4
import sys
5 6
import unittest

7
from test.support import (TESTFN, skip_unless_symlink,
8
                          can_symlink, create_empty_file, change_cwd)
9

10

11 12 13 14 15
class GlobTests(unittest.TestCase):

    def norm(self, *parts):
        return os.path.normpath(os.path.join(self.tempdir, *parts))

16 17 18
    def joins(self, *tuples):
        return [os.path.join(self.tempdir, *parts) for parts in tuples]

19
    def mktemp(self, *parts):
20 21 22 23
        filename = self.norm(*parts)
        base, file = os.path.split(filename)
        if not os.path.exists(base):
            os.makedirs(base)
24
        create_empty_file(filename)
25 26

    def setUp(self):
27
        self.tempdir = TESTFN + "_dir"
28 29
        self.mktemp('a', 'D')
        self.mktemp('aab', 'F')
30 31
        self.mktemp('.aa', 'G')
        self.mktemp('.bb', 'H')
32 33
        self.mktemp('aaa', 'zzzF')
        self.mktemp('ZZZ')
34
        self.mktemp('EF')
35 36
        self.mktemp('a', 'bcd', 'EF')
        self.mktemp('a', 'bcd', 'efg', 'ha')
37
        if can_symlink():
38
            os.symlink(self.norm('broken'), self.norm('sym1'))
39 40
            os.symlink('broken', self.norm('sym2'))
            os.symlink(os.path.join('a', 'bcd'), self.norm('sym3'))
41 42

    def tearDown(self):
43
        shutil.rmtree(self.tempdir)
44

45
    def glob(self, *parts, **kwargs):
46 47 48 49 50
        if len(parts) == 1:
            pattern = parts[0]
        else:
            pattern = os.path.join(*parts)
        p = os.path.join(self.tempdir, pattern)
51 52
        res = glob.glob(p, **kwargs)
        self.assertEqual(list(glob.iglob(p, **kwargs)), res)
53
        bres = [os.fsencode(x) for x in res]
54 55
        self.assertEqual(glob.glob(os.fsencode(p), **kwargs), bres)
        self.assertEqual(list(glob.iglob(os.fsencode(p), **kwargs)), bres)
Johannes Gijsbers's avatar
Johannes Gijsbers committed
56
        return res
57 58

    def assertSequencesEqual_noorder(self, l1, l2):
59 60
        l1 = list(l1)
        l2 = list(l2)
61
        self.assertEqual(set(l1), set(l2))
62
        self.assertEqual(sorted(l1), sorted(l2))
63 64 65 66 67 68 69 70

    def test_glob_literal(self):
        eq = self.assertSequencesEqual_noorder
        eq(self.glob('a'), [self.norm('a')])
        eq(self.glob('a', 'D'), [self.norm('a', 'D')])
        eq(self.glob('aab'), [self.norm('aab')])
        eq(self.glob('zymurgy'), [])

71 72 73 74 75 76 77 78 79
        res = glob.glob('*')
        self.assertEqual({type(r) for r in res}, {str})
        res = glob.glob(os.path.join(os.curdir, '*'))
        self.assertEqual({type(r) for r in res}, {str})

        res = glob.glob(b'*')
        self.assertEqual({type(r) for r in res}, {bytes})
        res = glob.glob(os.path.join(os.fsencode(os.curdir), b'*'))
        self.assertEqual({type(r) for r in res}, {bytes})
80

81 82 83 84
    def test_glob_one_directory(self):
        eq = self.assertSequencesEqual_noorder
        eq(self.glob('a*'), map(self.norm, ['a', 'aab', 'aaa']))
        eq(self.glob('*a'), map(self.norm, ['a', 'aaa']))
85 86
        eq(self.glob('.*'), map(self.norm, ['.aa', '.bb']))
        eq(self.glob('?aa'), map(self.norm, ['aaa']))
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
        eq(self.glob('aa?'), map(self.norm, ['aaa', 'aab']))
        eq(self.glob('aa[ab]'), map(self.norm, ['aaa', 'aab']))
        eq(self.glob('*q'), [])

    def test_glob_nested_directory(self):
        eq = self.assertSequencesEqual_noorder
        if os.path.normcase("abCD") == "abCD":
            # case-sensitive filesystem
            eq(self.glob('a', 'bcd', 'E*'), [self.norm('a', 'bcd', 'EF')])
        else:
            # case insensitive filesystem
            eq(self.glob('a', 'bcd', 'E*'), [self.norm('a', 'bcd', 'EF'),
                                             self.norm('a', 'bcd', 'efg')])
        eq(self.glob('a', 'bcd', '*g'), [self.norm('a', 'bcd', 'efg')])

    def test_glob_directory_names(self):
        eq = self.assertSequencesEqual_noorder
        eq(self.glob('*', 'D'), [self.norm('a', 'D')])
        eq(self.glob('*', '*a'), [])
        eq(self.glob('a', '*', '*', '*a'),
           [self.norm('a', 'bcd', 'efg', 'ha')])
108 109
        eq(self.glob('?a?', '*F'), [self.norm('aaa', 'zzzF'),
                                    self.norm('aab', 'F')])
110

111
    def test_glob_directory_with_trailing_slash(self):
112
        # Patterns ending with a slash shouldn't match non-dirs
113
        res = glob.glob(self.norm('Z*Z') + os.sep)
114
        self.assertEqual(res, [])
115
        res = glob.glob(self.norm('ZZZ') + os.sep)
116
        self.assertEqual(res, [])
117
        # When there is a wildcard pattern which ends with os.sep, glob()
118
        # doesn't blow up.
119
        res = glob.glob(self.norm('aa*') + os.sep)
120
        self.assertEqual(len(res), 2)
121
        # either of these results is reasonable
122 123 124 125 126 127 128 129
        self.assertIn(set(res), [
                      {self.norm('aaa'), self.norm('aab')},
                      {self.norm('aaa') + os.sep, self.norm('aab') + os.sep},
                      ])

    def test_glob_bytes_directory_with_trailing_slash(self):
        # Same as test_glob_directory_with_trailing_slash, but with a
        # bytes argument.
130
        res = glob.glob(os.fsencode(self.norm('Z*Z') + os.sep))
131
        self.assertEqual(res, [])
132
        res = glob.glob(os.fsencode(self.norm('ZZZ') + os.sep))
133
        self.assertEqual(res, [])
134
        res = glob.glob(os.fsencode(self.norm('aa*') + os.sep))
135
        self.assertEqual(len(res), 2)
136 137 138 139 140 141
        # either of these results is reasonable
        self.assertIn(set(res), [
                      {os.fsencode(self.norm('aaa')),
                       os.fsencode(self.norm('aab'))},
                      {os.fsencode(self.norm('aaa') + os.sep),
                       os.fsencode(self.norm('aab') + os.sep)},
142
                      ])
143

144 145 146 147 148 149 150 151 152 153 154 155
    @skip_unless_symlink
    def test_glob_symlinks(self):
        eq = self.assertSequencesEqual_noorder
        eq(self.glob('sym3'), [self.norm('sym3')])
        eq(self.glob('sym3', '*'), [self.norm('sym3', 'EF'),
                                    self.norm('sym3', 'efg')])
        self.assertIn(self.glob('sym3' + os.sep),
                      [[self.norm('sym3')], [self.norm('sym3') + os.sep]])
        eq(self.glob('*', '*F'),
           [self.norm('aaa', 'zzzF'),
            self.norm('aab', 'F'), self.norm('sym3', 'EF')])

156
    @skip_unless_symlink
157
    def test_glob_broken_symlinks(self):
158
        eq = self.assertSequencesEqual_noorder
159 160
        eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2'),
                               self.norm('sym3')])
161 162
        eq(self.glob('sym1'), [self.norm('sym1')])
        eq(self.glob('sym2'), [self.norm('sym2')])
163

164 165 166 167 168 169 170 171 172 173 174 175
    @unittest.skipUnless(sys.platform == "win32", "Win32 specific test")
    def test_glob_magic_in_drive(self):
        eq = self.assertSequencesEqual_noorder
        eq(glob.glob('*:'), [])
        eq(glob.glob(b'*:'), [])
        eq(glob.glob('?:'), [])
        eq(glob.glob(b'?:'), [])
        eq(glob.glob('\\\\?\\c:\\'), ['\\\\?\\c:\\'])
        eq(glob.glob(b'\\\\?\\c:\\'), [b'\\\\?\\c:\\'])
        eq(glob.glob('\\\\*\\*\\'), [])
        eq(glob.glob(b'\\\\*\\*\\'), [])

176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
    def check_escape(self, arg, expected):
        self.assertEqual(glob.escape(arg), expected)
        self.assertEqual(glob.escape(os.fsencode(arg)), os.fsencode(expected))

    def test_escape(self):
        check = self.check_escape
        check('abc', 'abc')
        check('[', '[[]')
        check('?', '[?]')
        check('*', '[*]')
        check('[[_/*?*/_]]', '[[][[]_/[*][?][*]/_]]')
        check('/[[_/*?*/_]]/', '/[[][[]_/[*][?][*]/_]]/')

    @unittest.skipUnless(sys.platform == "win32", "Win32 specific test")
    def test_escape_windows(self):
        check = self.check_escape
        check('?:?', '?:[?]')
        check('*:*', '*:[*]')
        check(r'\\?\c:\?', r'\\?\c:\[?]')
        check(r'\\*\*\*', r'\\*\*\[*]')
        check('//?/c:/?', '//?/c:/[?]')
        check('//*/*/*', '//*/*/[*]')
198

199 200 201 202 203
    def rglob(self, *parts, **kwargs):
        return self.glob(*parts, recursive=True, **kwargs)

    def test_recursive_glob(self):
        eq = self.assertSequencesEqual_noorder
204
        full = [('EF',), ('ZZZ',),
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
                ('a',), ('a', 'D'),
                ('a', 'bcd'),
                ('a', 'bcd', 'EF'),
                ('a', 'bcd', 'efg'),
                ('a', 'bcd', 'efg', 'ha'),
                ('aaa',), ('aaa', 'zzzF'),
                ('aab',), ('aab', 'F'),
               ]
        if can_symlink():
            full += [('sym1',), ('sym2',),
                     ('sym3',),
                     ('sym3', 'EF'),
                     ('sym3', 'efg'),
                     ('sym3', 'efg', 'ha'),
                    ]
        eq(self.rglob('**'), self.joins(('',), *full))
221 222
        eq(self.rglob(os.curdir, '**'),
            self.joins((os.curdir, ''), *((os.curdir,) + i for i in full)))
223 224 225 226 227 228 229 230 231 232
        dirs = [('a', ''), ('a', 'bcd', ''), ('a', 'bcd', 'efg', ''),
                ('aaa', ''), ('aab', '')]
        if can_symlink():
            dirs += [('sym3', ''), ('sym3', 'efg', '')]
        eq(self.rglob('**', ''), self.joins(('',), *dirs))

        eq(self.rglob('a', '**'), self.joins(
            ('a', ''), ('a', 'D'), ('a', 'bcd'), ('a', 'bcd', 'EF'),
            ('a', 'bcd', 'efg'), ('a', 'bcd', 'efg', 'ha')))
        eq(self.rglob('a**'), self.joins(('a',), ('aaa',), ('aab',)))
233
        expect = [('a', 'bcd', 'EF'), ('EF',)]
234 235 236
        if can_symlink():
            expect += [('sym3', 'EF')]
        eq(self.rglob('**', 'EF'), self.joins(*expect))
237
        expect = [('a', 'bcd', 'EF'), ('aaa', 'zzzF'), ('aab', 'F'), ('EF',)]
238 239 240 241 242 243 244 245
        if can_symlink():
            expect += [('sym3', 'EF')]
        eq(self.rglob('**', '*F'), self.joins(*expect))
        eq(self.rglob('**', '*F', ''), [])
        eq(self.rglob('**', 'bcd', '*'), self.joins(
            ('a', 'bcd', 'EF'), ('a', 'bcd', 'efg')))
        eq(self.rglob('a', '**', 'bcd'), self.joins(('a', 'bcd')))

246
        with change_cwd(self.tempdir):
247 248 249 250
            join = os.path.join
            eq(glob.glob('**', recursive=True), [join(*i) for i in full])
            eq(glob.glob(join('**', ''), recursive=True),
                [join(*i) for i in dirs])
251 252 253 254 255 256 257 258
            eq(glob.glob(join('**', '*'), recursive=True),
                [join(*i) for i in full])
            eq(glob.glob(join(os.curdir, '**'), recursive=True),
                [join(os.curdir, '')] + [join(os.curdir, *i) for i in full])
            eq(glob.glob(join(os.curdir, '**', ''), recursive=True),
                [join(os.curdir, '')] + [join(os.curdir, *i) for i in dirs])
            eq(glob.glob(join(os.curdir, '**', '*'), recursive=True),
                [join(os.curdir, *i) for i in full])
259 260 261
            eq(glob.glob(join('**','zz*F'), recursive=True),
                [join('aaa', 'zzzF')])
            eq(glob.glob('**zz*F', recursive=True), [])
262
            expect = [join('a', 'bcd', 'EF'), 'EF']
263 264 265 266 267 268 269 270 271 272 273 274
            if can_symlink():
                expect += [join('sym3', 'EF')]
            eq(glob.glob(join('**', 'EF'), recursive=True), expect)


@skip_unless_symlink
class SymlinkLoopGlobTests(unittest.TestCase):

    def test_selflink(self):
        tempdir = TESTFN + "_dir"
        os.makedirs(tempdir)
        self.addCleanup(shutil.rmtree, tempdir)
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
        with change_cwd(tempdir):
            os.makedirs('dir')
            create_empty_file(os.path.join('dir', 'file'))
            os.symlink(os.curdir, os.path.join('dir', 'link'))

            results = glob.glob('**', recursive=True)
            self.assertEqual(len(results), len(set(results)))
            results = set(results)
            depth = 0
            while results:
                path = os.path.join(*(['dir'] + ['link'] * depth))
                self.assertIn(path, results)
                results.remove(path)
                if not results:
                    break
                path = os.path.join(path, 'file')
                self.assertIn(path, results)
                results.remove(path)
                depth += 1

            results = glob.glob(os.path.join('**', 'file'), recursive=True)
            self.assertEqual(len(results), len(set(results)))
            results = set(results)
            depth = 0
            while results:
                path = os.path.join(*(['dir'] + ['link'] * depth + ['file']))
                self.assertIn(path, results)
                results.remove(path)
                depth += 1

            results = glob.glob(os.path.join('**', ''), recursive=True)
            self.assertEqual(len(results), len(set(results)))
            results = set(results)
            depth = 0
            while results:
                path = os.path.join(*(['dir'] + ['link'] * depth + ['']))
                self.assertIn(path, results)
                results.remove(path)
                depth += 1
314 315 316


if __name__ == "__main__":
317
    unittest.main()