Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6e5c8f9

Browse files
committed
#16618: Make glob.glob match consistently across strings and bytes
Fixes handling of leading dots. Patch by Serhiy Storchaka.
2 parents 513762f + 6f52027 commit 6e5c8f9

3 files changed

Lines changed: 59 additions & 30 deletions

File tree

Lib/glob.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ def glob1(dirname, pattern):
5757
names = os.listdir(dirname)
5858
except OSError:
5959
return []
60-
if pattern[0] != '.':
61-
names = [x for x in names if x[0] != '.']
60+
if not _ishidden(pattern):
61+
names = [x for x in names if not _ishidden(x)]
6262
return fnmatch.filter(names, pattern)
6363

6464
def glob0(dirname, basename):
@@ -82,3 +82,6 @@ def has_magic(s):
8282
else:
8383
match = magic_check.search(s)
8484
return match is not None
85+
86+
def _ishidden(path):
87+
return path[0] in ('.', b'.'[0])

Lib/test/test_glob.py

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import unittest
2-
from test.support import (run_unittest, TESTFN, skip_unless_symlink,
3-
can_symlink, create_empty_file)
41
import glob
52
import os
63
import shutil
74
import sys
5+
import unittest
6+
7+
from test.support import (run_unittest, TESTFN, skip_unless_symlink,
8+
can_symlink, create_empty_file)
89

910

1011
class GlobTests(unittest.TestCase):
@@ -31,7 +32,8 @@ def setUp(self):
3132
self.mktemp('a', 'bcd', 'efg', 'ha')
3233
if can_symlink():
3334
os.symlink(self.norm('broken'), self.norm('sym1'))
34-
os.symlink(self.norm('broken'), self.norm('sym2'))
35+
os.symlink('broken', self.norm('sym2'))
36+
os.symlink(os.path.join('a', 'bcd'), self.norm('sym3'))
3537

3638
def tearDown(self):
3739
shutil.rmtree(self.tempdir)
@@ -44,10 +46,16 @@ def glob(self, *parts):
4446
p = os.path.join(self.tempdir, pattern)
4547
res = glob.glob(p)
4648
self.assertEqual(list(glob.iglob(p)), res)
49+
bres = [os.fsencode(x) for x in res]
50+
self.assertEqual(glob.glob(os.fsencode(p)), bres)
51+
self.assertEqual(list(glob.iglob(os.fsencode(p))), bres)
4752
return res
4853

4954
def assertSequencesEqual_noorder(self, l1, l2):
55+
l1 = list(l1)
56+
l2 = list(l2)
5057
self.assertEqual(set(l1), set(l2))
58+
self.assertEqual(sorted(l1), sorted(l2))
5159

5260
def test_glob_literal(self):
5361
eq = self.assertSequencesEqual_noorder
@@ -56,15 +64,15 @@ def test_glob_literal(self):
5664
eq(self.glob('aab'), [self.norm('aab')])
5765
eq(self.glob('zymurgy'), [])
5866

59-
# test return types are unicode, but only if os.listdir
60-
# returns unicode filenames
61-
uniset = set([str])
62-
tmp = os.listdir('.')
63-
if set(type(x) for x in tmp) == uniset:
64-
u1 = glob.glob('*')
65-
u2 = glob.glob('./*')
66-
self.assertEqual(set(type(r) for r in u1), uniset)
67-
self.assertEqual(set(type(r) for r in u2), uniset)
67+
res = glob.glob('*')
68+
self.assertEqual({type(r) for r in res}, {str})
69+
res = glob.glob(os.path.join(os.curdir, '*'))
70+
self.assertEqual({type(r) for r in res}, {str})
71+
72+
res = glob.glob(b'*')
73+
self.assertEqual({type(r) for r in res}, {bytes})
74+
res = glob.glob(os.path.join(os.fsencode(os.curdir), b'*'))
75+
self.assertEqual({type(r) for r in res}, {bytes})
6876

6977
def test_glob_one_directory(self):
7078
eq = self.assertSequencesEqual_noorder
@@ -93,20 +101,20 @@ def test_glob_directory_names(self):
93101
eq(self.glob('*', '*a'), [])
94102
eq(self.glob('a', '*', '*', '*a'),
95103
[self.norm('a', 'bcd', 'efg', 'ha')])
96-
eq(self.glob('?a?', '*F'), map(self.norm, [os.path.join('aaa', 'zzzF'),
97-
os.path.join('aab', 'F')]))
104+
eq(self.glob('?a?', '*F'), [self.norm('aaa', 'zzzF'),
105+
self.norm('aab', 'F')])
98106

99107
def test_glob_directory_with_trailing_slash(self):
100108
# Patterns ending with a slash shouldn't match non-dirs
101-
res = glob.glob(os.path.join(self.tempdir, 'Z*Z') + os.sep)
109+
res = glob.glob(self.norm('Z*Z') + os.sep)
102110
self.assertEqual(res, [])
103-
res = glob.glob(os.path.join(self.tempdir, 'ZZZ') + os.sep)
111+
res = glob.glob(self.norm('ZZZ') + os.sep)
104112
self.assertEqual(res, [])
105-
# When there is wildcard pattern which ends with os.sep, glob()
113+
# When there is a wildcard pattern which ends with os.sep, glob()
106114
# doesn't blow up.
107-
res = glob.glob(os.path.join(self.tempdir, 'aa*') + os.sep)
115+
res = glob.glob(self.norm('aa*') + os.sep)
108116
self.assertEqual(len(res), 2)
109-
# either of these results are reasonable
117+
# either of these results is reasonable
110118
self.assertIn(set(res), [
111119
{self.norm('aaa'), self.norm('aab')},
112120
{self.norm('aaa') + os.sep, self.norm('aab') + os.sep},
@@ -115,22 +123,37 @@ def test_glob_directory_with_trailing_slash(self):
115123
def test_glob_bytes_directory_with_trailing_slash(self):
116124
# Same as test_glob_directory_with_trailing_slash, but with a
117125
# bytes argument.
118-
res = glob.glob(os.fsencode(os.path.join(self.tempdir, 'Z*Z') + os.sep))
126+
res = glob.glob(os.fsencode(self.norm('Z*Z') + os.sep))
119127
self.assertEqual(res, [])
120-
res = glob.glob(os.fsencode(os.path.join(self.tempdir, 'ZZZ') + os.sep))
128+
res = glob.glob(os.fsencode(self.norm('ZZZ') + os.sep))
121129
self.assertEqual(res, [])
122-
res = glob.glob(os.fsencode(os.path.join(self.tempdir, 'aa*') + os.sep))
130+
res = glob.glob(os.fsencode(self.norm('aa*') + os.sep))
123131
self.assertEqual(len(res), 2)
124-
# either of these results are reasonable
125-
self.assertIn({os.fsdecode(x) for x in res}, [
126-
{self.norm('aaa'), self.norm('aab')},
127-
{self.norm('aaa') + os.sep, self.norm('aab') + os.sep},
132+
# either of these results is reasonable
133+
self.assertIn(set(res), [
134+
{os.fsencode(self.norm('aaa')),
135+
os.fsencode(self.norm('aab'))},
136+
{os.fsencode(self.norm('aaa') + os.sep),
137+
os.fsencode(self.norm('aab') + os.sep)},
128138
])
129139

140+
@skip_unless_symlink
141+
def test_glob_symlinks(self):
142+
eq = self.assertSequencesEqual_noorder
143+
eq(self.glob('sym3'), [self.norm('sym3')])
144+
eq(self.glob('sym3', '*'), [self.norm('sym3', 'EF'),
145+
self.norm('sym3', 'efg')])
146+
self.assertIn(self.glob('sym3' + os.sep),
147+
[[self.norm('sym3')], [self.norm('sym3') + os.sep]])
148+
eq(self.glob('*', '*F'),
149+
[self.norm('aaa', 'zzzF'),
150+
self.norm('aab', 'F'), self.norm('sym3', 'EF')])
151+
130152
@skip_unless_symlink
131153
def test_glob_broken_symlinks(self):
132154
eq = self.assertSequencesEqual_noorder
133-
eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2')])
155+
eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2'),
156+
self.norm('sym3')])
134157
eq(self.glob('sym1'), [self.norm('sym1')])
135158
eq(self.glob('sym2'), [self.norm('sym2')])
136159

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ Core and Builtins
190190
Library
191191
-------
192192

193+
- Issue #16618: Make glob.glob match consistently across strings and bytes
194+
regarding leading dots. Patch by Serhiy Storchaka.
195+
193196
- Issue #16788: Add samestat to Lib/ntpath.py
194197

195198
- Issue #16702: test_urllib2_localnet tests now correctly ignores proxies for

0 commit comments

Comments
 (0)