~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_globbing.py

  • Committer: Martin Pool
  • Date: 2005-05-13 00:57:32 UTC
  • Revision ID: mbp@sourcefrog.net-20050513005732-26b0a3042cbb57d1
- more notes on tagging

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
2
 
# -*- coding: utf-8 -*-
3
 
#
4
 
# This program is free software; you can redistribute it and/or modify
5
 
# it under the terms of the GNU General Public License as published by
6
 
# the Free Software Foundation; either version 2 of the License, or
7
 
# (at your option) any later version.
8
 
#
9
 
# This program is distributed in the hope that it will be useful,
10
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
# GNU General Public License for more details.
13
 
#
14
 
# You should have received a copy of the GNU General Public License
15
 
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 
18
 
from bzrlib.globbing import (
19
 
    Globster,
20
 
    )
21
 
from bzrlib.tests import (
22
 
    TestCase, 
23
 
    TestCaseInTempDir,
24
 
    )
25
 
 
26
 
 
27
 
class TestGlobster(TestCase):
28
 
 
29
 
    def assertMatch(self, matchset, glob_prefix=None):
30
 
        for glob, positive, negative in matchset:
31
 
            if glob_prefix:
32
 
                glob = glob_prefix + glob
33
 
            globster = Globster([glob])
34
 
            for name in positive:
35
 
                self.failUnless(globster.match(name), repr(
36
 
                    u'name "%s" does not match glob "%s" (re=%s)' %
37
 
                    (name, glob, globster._regex_patterns[0][0].pattern)))
38
 
            for name in negative:
39
 
                self.failIf(globster.match(name), repr(
40
 
                    u'name "%s" does match glob "%s" (re=%s)' %
41
 
                    (name, glob, globster._regex_patterns[0][0].pattern)))
42
 
 
43
 
    def assertMatchBasenameAndFullpath(self, matchset):
44
 
        # test basename matcher
45
 
        self.assertMatch(matchset)
46
 
        # test fullpath matcher
47
 
        self.assertMatch(matchset, glob_prefix='./')
48
 
 
49
 
    def test_char_group_digit(self):
50
 
        self.assertMatchBasenameAndFullpath([
51
 
            # The definition of digit this uses includes arabic digits from
52
 
            # non-latin scripts (arabic, indic, etc.) and subscript/superscript
53
 
            # digits, but neither roman numerals nor vulgar fractions.
54
 
            (u'[[:digit:]]',
55
 
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9'],
56
 
             [u'T', u'q', u' ', u'\u8336', u'.']),
57
 
            (u'[^[:digit:]]',
58
 
             [u'T', u'q', u' ', u'\u8336', u'.'],
59
 
             [u'0', u'5', u'\u0663', u'\u06f9', u'\u0f21', u'\xb9']),
60
 
            ])
61
 
 
62
 
    def test_char_group_space(self):
63
 
        self.assertMatchBasenameAndFullpath([
64
 
            (u'[[:space:]]',
65
 
             [u' ', u'\t', u'\n', u'\xa0', u'\u2000', u'\u2002'],
66
 
             [u'a', u'-', u'\u8336', u'.']),
67
 
            (u'[^[:space:]]',
68
 
             [u'a', u'-', u'\u8336', u'.'],
69
 
             [u' ', u'\t', u'\n', u'\xa0', u'\u2000', u'\u2002']),
70
 
            ])
71
 
 
72
 
    def test_char_group_alnum(self):
73
 
        self.assertMatchBasenameAndFullpath([
74
 
            (u'[[:alnum:]]',
75
 
             [u'a', u'Z', u'\u017e', u'\u8336'],
76
 
             [u':', u'-', u'\u25cf', u'.']),
77
 
            (u'[^[:alnum:]]',
78
 
             [u':', u'-', u'\u25cf', u'.'],
79
 
             [u'a']),
80
 
            ])
81
 
 
82
 
    def test_char_group_ascii(self):
83
 
        self.assertMatchBasenameAndFullpath([
84
 
            (u'[[:ascii:]]',
85
 
             [u'a', u'Q', u'^', u'.'],
86
 
             [u'\xcc', u'\u8336']),
87
 
            (u'[^[:ascii:]]',
88
 
             [u'\xcc', u'\u8336'],
89
 
             [u'a', u'Q', u'^', u'.']),
90
 
            ])
91
 
 
92
 
    def test_char_group_blank(self):
93
 
        self.assertMatchBasenameAndFullpath([
94
 
            (u'[[:blank:]]',
95
 
             [u'\t'],
96
 
             [u'x', u'y', u'z', u'.']),
97
 
            (u'[^[:blank:]]',
98
 
             [u'x', u'y', u'z', u'.'],
99
 
             [u'\t']),
100
 
            ])
101
 
 
102
 
    def test_char_group_cntrl(self):
103
 
        self.assertMatchBasenameAndFullpath([
104
 
            (u'[[:cntrl:]]',
105
 
             [u'\b', u'\t', '\x7f'],
106
 
             [u'a', u'Q', u'\u8336', u'.']),
107
 
            (u'[^[:cntrl:]]',
108
 
             [u'a', u'Q', u'\u8336', u'.'],
109
 
             [u'\b', u'\t', '\x7f']),
110
 
            ])
111
 
 
112
 
    def test_char_group_range(self):
113
 
        self.assertMatchBasenameAndFullpath([
114
 
            (u'[a-z]',
115
 
             [u'a', u'q', u'f'],
116
 
             [u'A', u'Q', u'F']),
117
 
            (u'[^a-z]',
118
 
             [u'A', u'Q', u'F'],
119
 
             [u'a', u'q', u'f']),
120
 
            (u'[!a-z]foo',
121
 
             [u'Afoo', u'.foo'],
122
 
             [u'afoo', u'ABfoo']),
123
 
            (u'foo[!a-z]bar',
124
 
             [u'fooAbar', u'foo.bar'],
125
 
             [u'foojbar']),
126
 
            (u'[\x20-\x30\u8336]',
127
 
             [u'\040', u'\044', u'\u8336'],
128
 
             [u'\x1f']),
129
 
            (u'[^\x20-\x30\u8336]',
130
 
             [u'\x1f'],
131
 
             [u'\040', u'\044', u'\u8336']),
132
 
            ])
133
 
 
134
 
    def test_regex(self):
135
 
        self.assertMatch([
136
 
            (u'RE:(a|b|c+)',
137
 
             [u'a', u'b', u'ccc'],
138
 
             [u'd', u'aa', u'c+', u'-a']),
139
 
            (u'RE:(?:a|b|c+)',
140
 
             [u'a', u'b', u'ccc'],
141
 
             [u'd', u'aa', u'c+', u'-a']),
142
 
            (u'RE:(?P<a>.)(?P=a)',
143
 
             [u'a'],
144
 
             [u'ab', u'aa', u'aaa']),
145
 
            # test we can handle odd numbers of trailing backslashes
146
 
            (u'RE:a\\\\\\',
147
 
             [u'a\\'],
148
 
             [u'a', u'ab', u'aa', u'aaa']),
149
 
            ])
150
 
 
151
 
    def test_question_mark(self):
152
 
        self.assertMatch([
153
 
            (u'?foo',
154
 
             [u'xfoo', u'bar/xfoo', u'bar/\u8336foo', u'.foo', u'bar/.foo'],
155
 
             [u'bar/foo', u'foo']),
156
 
            (u'foo?bar',
157
 
             [u'fooxbar', u'foo.bar', u'foo\u8336bar', u'qyzzy/foo.bar'],
158
 
             [u'foo/bar']),
159
 
            (u'foo/?bar',
160
 
             [u'foo/xbar', u'foo/\u8336bar', u'foo/.bar'],
161
 
             [u'foo/bar', u'bar/foo/xbar']),
162
 
            ])
163
 
 
164
 
    def test_asterisk(self):
165
 
        self.assertMatch([
166
 
            (u'x*x',
167
 
             [u'xx', u'x.x', u'x\u8336..x', u'\u8336/x.x', u'x.y.x'],
168
 
             [u'x/x', u'bar/x/bar/x', u'bax/abaxab']),
169
 
            (u'foo/*x',
170
 
             [u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
171
 
             [u'foo/bar/bax']),
172
 
            (u'*/*x',
173
 
             [u'\u8336/x', u'foo/x', u'foo/bax', u'x/a.x', u'.foo/x', 
174
 
              u'\u8336/.x', u'foo/.q.x'],
175
 
             [u'foo/bar/bax']),
176
 
            (u'f*',
177
 
             [u'foo', u'foo.bar'],
178
 
             [u'.foo', u'foo/bar', u'foo/.bar']),
179
 
            (u'*bar',
180
 
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar', 
181
 
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
182
 
             []),
183
 
            ])
184
 
 
185
 
    def test_double_asterisk(self):
186
 
        self.assertMatch([
187
 
            # expected uses of double asterisk
188
 
            (u'foo/**/x',
189
 
             [u'foo/x', u'foo/bar/x'],
190
 
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
191
 
            (u'**/bar',
192
 
             [u'bar', u'foo/bar'],
193
 
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar', 
194
 
              u'.bar', u'foo/.bar']),
195
 
            # check that we ignore extra *s, so *** is treated like ** not *.
196
 
            (u'foo/***/x',
197
 
             [u'foo/x', u'foo/bar/x'],
198
 
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
199
 
            (u'***/bar',
200
 
             [u'bar', u'foo/bar'],
201
 
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar', 
202
 
              u'.bar', u'foo/.bar']),
203
 
            # the remaining tests check that ** is interpreted as *
204
 
            # unless it is a whole path component
205
 
            (u'x**/x',
206
 
             [u'x\u8336/x', u'x/x'],
207
 
             [u'xx', u'x.x', u'bar/x/bar/x', u'x.y.x', u'x/y/x']),
208
 
            (u'x**x',
209
 
             [u'xx', u'x.x', u'x\u8336..x', u'foo/x.x', u'x.y.x'],
210
 
             [u'bar/x/bar/x', u'xfoo/bar/x', u'x/x', u'bax/abaxab']),
211
 
            (u'foo/**x',
212
 
             [u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
213
 
             [u'foo/bar/bax']),
214
 
            (u'f**',
215
 
             [u'foo', u'foo.bar'],
216
 
             [u'.foo', u'foo/bar', u'foo/.bar']),
217
 
            (u'**bar',
218
 
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar', 
219
 
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
220
 
             []),
221
 
            ])
222
 
 
223
 
    def test_leading_dot_slash(self):
224
 
        self.assertMatch([
225
 
            (u'./foo',
226
 
             [u'foo'],
227
 
             [u'\u8336/foo', u'barfoo', u'x/y/foo']),
228
 
            (u'./f*',
229
 
             [u'foo'],
230
 
             [u'foo/bar', u'foo/.bar', u'x/foo/y']),
231
 
            ])
232
 
 
233
 
    def test_backslash(self):
234
 
        self.assertMatch([
235
 
            (u'.\\foo',
236
 
             [u'foo'],
237
 
             [u'\u8336/foo', u'barfoo', u'x/y/foo']),
238
 
            (u'.\\f*',
239
 
             [u'foo'],
240
 
             [u'foo/bar', u'foo/.bar', u'x/foo/y']),
241
 
            (u'foo\\**\\x',
242
 
             [u'foo/x', u'foo/bar/x'],
243
 
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
244
 
            ])
245
 
 
246
 
    def test_trailing_slash(self):
247
 
        self.assertMatch([
248
 
            (u'./foo/',
249
 
             [u'foo'],
250
 
             [u'\u8336/foo', u'barfoo', u'x/y/foo']),
251
 
            (u'.\\foo\\',
252
 
             [u'foo'],
253
 
             [u'foo/', u'\u8336/foo', u'barfoo', u'x/y/foo']),
254
 
            ])
255
 
 
256
 
    def test_leading_asterisk_dot(self):
257
 
        self.assertMatch([
258
 
            (u'*.x',
259
 
             [u'foo/bar/baz.x', u'\u8336/Q.x', u'foo.y.x', u'.foo.x', 
260
 
              u'bar/.foo.x', u'.x',],
261
 
             [u'foo.x.y']),
262
 
            (u'foo/*.bar',
263
 
             [u'foo/b.bar', u'foo/a.b.bar', u'foo/.bar'],
264
 
             [u'foo/bar']),
265
 
            (u'*.~*',
266
 
             [u'foo.py.~1~', u'.foo.py.~1~'],
267
 
             []),
268
 
            ])
269
 
 
270
 
    def test_end_anchor(self):
271
 
        self.assertMatch([
272
 
            (u'*.333',
273
 
             [u'foo.333'],
274
 
             [u'foo.3']),
275
 
            (u'*.3',
276
 
             [u'foo.3'],
277
 
             [u'foo.333']),
278
 
            ])
279
 
 
280
 
    def test_mixed_globs(self):
281
 
        """tests handling of combinations of path type matches.
282
 
 
283
 
        The types being extension, basename and full path.
284
 
        """
285
 
        patterns = [ u'*.foo', u'.*.swp', u'./*.png']
286
 
        globster = Globster(patterns)
287
 
        self.assertEqual(u'*.foo', globster.match('bar.foo'))
288
 
        self.assertEqual(u'./*.png', globster.match('foo.png'))
289
 
        self.assertEqual(None, globster.match('foo/bar.png'))
290
 
        self.assertEqual(u'.*.swp', globster.match('foo/.bar.py.swp'))
291
 
 
292
 
    def test_large_globset(self):
293
 
        """tests that the globster can handle a large set of patterns.
294
 
 
295
 
        Large is defined as more than supported by python regex groups, 
296
 
        i.e. 99.
297
 
        This test assumes the globs are broken into regexs containing 99
298
 
        groups.
299
 
        """
300
 
        patterns = [ u'*.%03d' % i for i in xrange(0,300) ]
301
 
        globster = Globster(patterns)
302
 
        # test the fence posts
303
 
        for x in (0,98,99,197,198,296,297,299):
304
 
            filename = u'foo.%03d' % x
305
 
            self.assertEqual(patterns[x],globster.match(filename))
306
 
        self.assertEqual(None,globster.match('foobar.300'))
307