1import glob
2import os
3import shutil
4import sys
5import unittest
6
7from test.test_support import run_unittest, TESTFN
8
9
10def fsdecode(s):
11    return unicode(s, sys.getfilesystemencoding())
12
13
14class GlobTests(unittest.TestCase):
15
16    def norm(self, *parts):
17        return os.path.normpath(os.path.join(self.tempdir, *parts))
18
19    def mktemp(self, *parts):
20        filename = self.norm(*parts)
21        base, file = os.path.split(filename)
22        if not os.path.exists(base):
23            os.makedirs(base)
24        f = open(filename, 'w')
25        f.close()
26
27    def setUp(self):
28        self.tempdir = TESTFN + "_dir"
29        self.mktemp('a', 'D')
30        self.mktemp('aab', 'F')
31        self.mktemp('.aa', 'G')
32        self.mktemp('.bb', 'H')
33        self.mktemp('aaa', 'zzzF')
34        self.mktemp('ZZZ')
35        self.mktemp('a', 'bcd', 'EF')
36        self.mktemp('a', 'bcd', 'efg', 'ha')
37        if hasattr(os, 'symlink'):
38            os.symlink(self.norm('broken'), self.norm('sym1'))
39            os.symlink('broken', self.norm('sym2'))
40            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):
46        if len(parts) == 1:
47            pattern = parts[0]
48        else:
49            pattern = os.path.join(*parts)
50        p = os.path.join(self.tempdir, pattern)
51        res = glob.glob(p)
52        self.assertEqual(list(glob.iglob(p)), res)
53        ures = [fsdecode(x) for x in res]
54        self.assertEqual(glob.glob(fsdecode(p)), ures)
55        self.assertEqual(list(glob.iglob(fsdecode(p))), ures)
56        return res
57
58    def assertSequencesEqual_noorder(self, l1, l2):
59        l1 = list(l1)
60        l2 = list(l2)
61        self.assertEqual(set(l1), set(l2))
62        self.assertEqual(sorted(l1), sorted(l2))
63
64    def test_glob_literal(self):
65        eq = self.assertSequencesEqual_noorder
66        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
71        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        # test return types are unicode, but only if os.listdir
77        # returns unicode filenames
78        tmp = os.listdir(fsdecode(os.curdir))
79        if {type(x) for x in tmp} == {unicode}:
80            res = glob.glob(u'*')
81            self.assertEqual({type(r) for r in res}, {unicode})
82            res = glob.glob(os.path.join(fsdecode(os.curdir), u'*'))
83            self.assertEqual({type(r) for r in res}, {unicode})
84
85    def test_glob_one_directory(self):
86        eq = self.assertSequencesEqual_noorder
87        eq(self.glob('a*'), map(self.norm, ['a', 'aab', 'aaa']))
88        eq(self.glob('*a'), map(self.norm, ['a', 'aaa']))
89        eq(self.glob('.*'), map(self.norm, ['.aa', '.bb']))
90        eq(self.glob('?aa'), map(self.norm, ['aaa']))
91        eq(self.glob('aa?'), map(self.norm, ['aaa', 'aab']))
92        eq(self.glob('aa[ab]'), map(self.norm, ['aaa', 'aab']))
93        eq(self.glob('*q'), [])
94
95    def test_glob_nested_directory(self):
96        eq = self.assertSequencesEqual_noorder
97        if os.path.normcase("abCD") == "abCD":
98            # case-sensitive filesystem
99            eq(self.glob('a', 'bcd', 'E*'), [self.norm('a', 'bcd', 'EF')])
100        else:
101            # case insensitive filesystem
102            eq(self.glob('a', 'bcd', 'E*'), [self.norm('a', 'bcd', 'EF'),
103                                             self.norm('a', 'bcd', 'efg')])
104        eq(self.glob('a', 'bcd', '*g'), [self.norm('a', 'bcd', 'efg')])
105
106    def test_glob_directory_names(self):
107        eq = self.assertSequencesEqual_noorder
108        eq(self.glob('*', 'D'), [self.norm('a', 'D')])
109        eq(self.glob('*', '*a'), [])
110        eq(self.glob('a', '*', '*', '*a'),
111           [self.norm('a', 'bcd', 'efg', 'ha')])
112        eq(self.glob('?a?', '*F'), [self.norm('aaa', 'zzzF'),
113                                    self.norm('aab', 'F')])
114
115    def test_glob_directory_with_trailing_slash(self):
116        # Patterns ending with a slash shouldn't match non-dirs
117        res = glob.glob(self.norm('Z*Z') + os.sep)
118        self.assertEqual(res, [])
119        res = glob.glob(self.norm('ZZZ') + os.sep)
120        self.assertEqual(res, [])
121        # When there is a wildcard pattern which ends with os.sep, glob()
122        # doesn't blow up.
123        res = glob.glob(self.norm('aa*') + os.sep)
124        self.assertEqual(len(res), 2)
125        # either of these results is reasonable
126        self.assertIn(set(res), [
127                      {self.norm('aaa'), self.norm('aab')},
128                      {self.norm('aaa') + os.sep, self.norm('aab') + os.sep},
129                      ])
130
131    def test_glob_unicode_directory_with_trailing_slash(self):
132        # Same as test_glob_directory_with_trailing_slash, but with an
133        # unicode argument.
134        res = glob.glob(fsdecode(self.norm('Z*Z') + os.sep))
135        self.assertEqual(res, [])
136        res = glob.glob(fsdecode(self.norm('ZZZ') + os.sep))
137        self.assertEqual(res, [])
138        res = glob.glob(fsdecode(self.norm('aa*') + os.sep))
139        self.assertEqual(len(res), 2)
140        # either of these results is reasonable
141        self.assertIn(set(res), [
142                      {fsdecode(self.norm('aaa')), fsdecode(self.norm('aab'))},
143                      {fsdecode(self.norm('aaa') + os.sep),
144                       fsdecode(self.norm('aab') + os.sep)},
145                      ])
146
147    @unittest.skipUnless(hasattr(os, 'symlink'), "Requires symlink support")
148    def test_glob_symlinks(self):
149        eq = self.assertSequencesEqual_noorder
150        eq(self.glob('sym3'), [self.norm('sym3')])
151        eq(self.glob('sym3', '*'), [self.norm('sym3', 'EF'),
152                                    self.norm('sym3', 'efg')])
153        self.assertIn(self.glob('sym3' + os.sep),
154                      [[self.norm('sym3')], [self.norm('sym3') + os.sep]])
155        eq(self.glob('*', '*F'),
156           [self.norm('aaa', 'zzzF'), self.norm('aab', 'F'),
157            self.norm('sym3', 'EF')])
158
159    @unittest.skipUnless(hasattr(os, 'symlink'), "Requires symlink support")
160    def test_glob_broken_symlinks(self):
161        eq = self.assertSequencesEqual_noorder
162        eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2'),
163                               self.norm('sym3')])
164        eq(self.glob('sym1'), [self.norm('sym1')])
165        eq(self.glob('sym2'), [self.norm('sym2')])
166
167    @unittest.skipUnless(sys.platform == "win32", "Win32 specific test")
168    def test_glob_magic_in_drive(self):
169        eq = self.assertSequencesEqual_noorder
170        eq(glob.glob('*:'), [])
171        eq(glob.glob(u'*:'), [])
172        eq(glob.glob('?:'), [])
173        eq(glob.glob(u'?:'), [])
174
175
176def test_main():
177    run_unittest(GlobTests)
178
179
180if __name__ == "__main__":
181    test_main()
182