~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_globbing.py

  • Committer: mbp at sourcefrog
  • Date: 2005-03-30 22:27:17 UTC
  • Revision ID: mbp@sourcefrog.net-20050330222717-027b5837127b938d
experiment with new nested inventory file format
not used by default yet

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
 
            (ur'[^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
 
            (ur'foo[!a-z]bar',
124
 
             [u'fooAbar', u'foo.bar'],
125
 
             [u'foojbar']),
126
 
            (ur'[\x20-\x30\u8336]',
127
 
             [u'\040', u'\044', u'\u8336'],
128
 
             [u'\x1f']),
129
 
            (ur'[^\x20-\x30\u8336]',
130
 
             [u'\x1f'],
131
 
             [u'\040', u'\044', u'\u8336']),
132
 
            ])
133
 
 
134
 
    def test_regex(self):
135
 
        self.assertMatch([
136
 
            (ur'RE:(a|b|c+)',
137
 
             [u'a', u'b', u'ccc'],
138
 
             [u'd', u'aa', u'c+', u'-a']),
139
 
            (ur'RE:(?:a|b|c+)',
140
 
             [u'a', u'b', u'ccc'],
141
 
             [u'd', u'aa', u'c+', u'-a']),
142
 
            (ur'RE:(?P<a>.)(?P=a)',
143
 
             [u'a'],
144
 
             [u'ab', u'aa', u'aaa']),
145
 
            ])
146
 
 
147
 
    def test_question_mark(self):
148
 
        self.assertMatch([
149
 
            (u'?foo',
150
 
             [u'xfoo', u'bar/xfoo', u'bar/\u8336foo', u'.foo', u'bar/.foo'],
151
 
             [u'bar/foo', u'foo']),
152
 
            (u'foo?bar',
153
 
             [u'fooxbar', u'foo.bar', u'foo\u8336bar', u'qyzzy/foo.bar'],
154
 
             [u'foo/bar']),
155
 
            (u'foo/?bar',
156
 
             [u'foo/xbar', u'foo/\u8336bar', u'foo/.bar'],
157
 
             [u'foo/bar', u'bar/foo/xbar']),
158
 
            ])
159
 
 
160
 
    def test_asterisk(self):
161
 
        self.assertMatch([
162
 
            (u'x*x',
163
 
             [u'xx', u'x.x', u'x\u8336..x', u'\u8336/x.x', u'x.y.x'],
164
 
             [u'x/x', u'bar/x/bar/x', u'bax/abaxab']),
165
 
            (u'foo/*x',
166
 
             [u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
167
 
             [u'foo/bar/bax']),
168
 
            (u'*/*x',
169
 
             [u'\u8336/x', u'foo/x', u'foo/bax', u'x/a.x', u'.foo/x', 
170
 
              u'\u8336/.x', u'foo/.q.x'],
171
 
             [u'foo/bar/bax']),
172
 
            (u'f*',
173
 
             [u'foo', u'foo.bar'],
174
 
             [u'.foo', u'foo/bar', u'foo/.bar']),
175
 
            (u'*bar',
176
 
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar', 
177
 
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
178
 
             []),
179
 
            ])
180
 
 
181
 
    def test_double_asterisk(self):
182
 
        self.assertMatch([
183
 
            # expected uses of double asterisk
184
 
            (u'foo/**/x',
185
 
             [u'foo/x', u'foo/bar/x'],
186
 
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
187
 
            (u'**/bar',
188
 
             [u'bar', u'foo/bar'],
189
 
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar', 
190
 
              u'.bar', u'foo/.bar']),
191
 
            # check that we ignore extra *s, so *** is treated like ** not *.
192
 
            (u'foo/***/x',
193
 
             [u'foo/x', u'foo/bar/x'],
194
 
             [u'foox', u'foo/bax', u'foo/.x', u'foo/bar/bax']),
195
 
            (u'***/bar',
196
 
             [u'bar', u'foo/bar'],
197
 
             [u'foobar', u'foo.bar', u'foo/foobar', u'foo/f.bar', 
198
 
              u'.bar', u'foo/.bar']),
199
 
            # the remaining tests check that ** is interpreted as *
200
 
            # unless it is a whole path component
201
 
            (u'x**/x',
202
 
             [u'x\u8336/x', u'x/x'],
203
 
             [u'xx', u'x.x', u'bar/x/bar/x', u'x.y.x', u'x/y/x']),
204
 
            (u'x**x',
205
 
             [u'xx', u'x.x', u'x\u8336..x', u'foo/x.x', u'x.y.x'],
206
 
             [u'bar/x/bar/x', u'xfoo/bar/x', u'x/x', u'bax/abaxab']),
207
 
            (u'foo/**x',
208
 
             [u'foo/x', u'foo/bax', u'foo/a.x', u'foo/.x', u'foo/.q.x'],
209
 
             [u'foo/bar/bax']),
210
 
            (u'f**',
211
 
             [u'foo', u'foo.bar'],
212
 
             [u'.foo', u'foo/bar', u'foo/.bar']),
213
 
            (u'**bar',
214
 
             [u'bar', u'foobar', ur'foo\nbar', u'foo.bar', u'foo/bar', 
215
 
              u'foo/foobar', u'foo/f.bar', u'.bar', u'foo/.bar'],
216
 
             []),
217
 
            ])
218
 
 
219
 
    def test_leading_dot_slash(self):
220
 
        self.assertMatch([
221
 
            (u'./foo',
222
 
             [u'foo'],
223
 
             [u'\u8336/foo', u'barfoo', u'x/y/foo']),
224
 
            (u'./f*',
225
 
             [u'foo'],
226
 
             [u'foo/bar', u'foo/.bar', u'x/foo/y']),
227
 
            ])
228
 
 
229
 
    def test_leading_asterisk_dot(self):
230
 
        self.assertMatch([
231
 
            (u'*.x',
232
 
             [u'foo/bar/baz.x', u'\u8336/Q.x', u'foo.y.x', u'.foo.x', 
233
 
              u'bar/.foo.x', u'.x',],
234
 
             [u'foo.x.y']),
235
 
            (u'foo/*.bar',
236
 
             [u'foo/b.bar', u'foo/a.b.bar', u'foo/.bar'],
237
 
             [u'foo/bar']),
238
 
            (u'*.~*',
239
 
             [u'foo.py.~1~', u'.foo.py.~1~'],
240
 
             []),
241
 
            ])
242
 
 
243
 
    def test_end_anchor(self):
244
 
        self.assertMatch([
245
 
            (u'*.333',
246
 
             [u'foo.333'],
247
 
             [u'foo.3']),
248
 
            (u'*.3',
249
 
             [u'foo.3'],
250
 
             [u'foo.333']),
251
 
            ])
252
 
 
253
 
    def test_mixed_globs(self):
254
 
        """tests handling of combinations of path type matches.
255
 
 
256
 
        The types being extension, basename and full path.
257
 
        """
258
 
        patterns = [ u'*.foo', u'.*.swp', u'./*.png']
259
 
        globster = Globster(patterns)
260
 
        self.assertEqual(u'*.foo', globster.match('bar.foo'))
261
 
        self.assertEqual(u'./*.png', globster.match('foo.png'))
262
 
        self.assertEqual(None, globster.match('foo/bar.png'))
263
 
        self.assertEqual(u'.*.swp', globster.match('foo/.bar.py.swp'))
264
 
 
265
 
    def test_large_globset(self):
266
 
        """tests that the globster can handle a large set of patterns.
267
 
 
268
 
        Large is defined as more than supported by python regex groups, 
269
 
        i.e. 99.
270
 
        This test assumes the globs are broken into regexs containing 99
271
 
        groups.
272
 
        """
273
 
        patterns = [ u'*.%03d' % i for i in xrange(0,300) ]
274
 
        globster = Globster(patterns)
275
 
        # test the fence posts
276
 
        for x in (0,98,99,197,198,296,297,299):
277
 
            filename = u'foo.%03d' % x
278
 
            self.assertEqual(patterns[x],globster.match(filename))
279
 
        self.assertEqual(None,globster.match('foobar.300'))
280