305 def binary(s): |
305 def binary(s): |
306 """return true if a string is binary data""" |
306 """return true if a string is binary data""" |
307 return bool(s and b'\0' in s) |
307 return bool(s and b'\0' in s) |
308 |
308 |
309 |
309 |
|
310 def _splitpattern(pattern): |
|
311 if pattern.startswith(b're:'): |
|
312 return b're', pattern[3:] |
|
313 elif pattern.startswith(b'literal:'): |
|
314 return b'literal', pattern[8:] |
|
315 return b'literal', pattern |
|
316 |
|
317 |
310 def stringmatcher(pattern, casesensitive=True): |
318 def stringmatcher(pattern, casesensitive=True): |
311 """ |
319 """ |
312 accepts a string, possibly starting with 're:' or 'literal:' prefix. |
320 accepts a string, possibly starting with 're:' or 'literal:' prefix. |
313 returns the matcher name, pattern, and matcher function. |
321 returns the matcher name, pattern, and matcher function. |
314 missing or unknown prefixes are treated as literal matches. |
322 missing or unknown prefixes are treated as literal matches. |
343 |
351 |
344 case insensitive literal matches |
352 case insensitive literal matches |
345 >>> itest(b'ABCDEFG', b'abc', b'def', b'abcdefg') |
353 >>> itest(b'ABCDEFG', b'abc', b'def', b'abcdefg') |
346 ('literal', 'ABCDEFG', [False, False, True]) |
354 ('literal', 'ABCDEFG', [False, False, True]) |
347 """ |
355 """ |
348 if pattern.startswith(b're:'): |
356 kind, pattern = _splitpattern(pattern) |
349 pattern = pattern[3:] |
357 if kind == b're': |
350 try: |
358 try: |
351 flags = 0 |
359 flags = 0 |
352 if not casesensitive: |
360 if not casesensitive: |
353 flags = remod.I |
361 flags = remod.I |
354 regex = remod.compile(pattern, flags) |
362 regex = remod.compile(pattern, flags) |
355 except remod.error as e: |
363 except remod.error as e: |
356 raise error.ParseError(_(b'invalid regular expression: %s') % e) |
364 raise error.ParseError(_(b'invalid regular expression: %s') % e) |
357 return b're', pattern, regex.search |
365 return kind, pattern, regex.search |
358 elif pattern.startswith(b'literal:'): |
366 elif kind == b'literal': |
359 pattern = pattern[8:] |
367 if casesensitive: |
360 |
368 match = pattern.__eq__ |
361 match = pattern.__eq__ |
369 else: |
362 |
370 ipat = encoding.lower(pattern) |
363 if not casesensitive: |
371 match = lambda s: ipat == encoding.lower(s) |
364 ipat = encoding.lower(pattern) |
372 return kind, pattern, match |
365 match = lambda s: ipat == encoding.lower(s) |
373 |
366 return b'literal', pattern, match |
374 raise error.ProgrammingError(b'unhandled pattern kind: %s' % kind) |
367 |
375 |
368 |
376 |
369 def shortuser(user): |
377 def shortuser(user): |
370 """Return a short representation of a user name or email address.""" |
378 """Return a short representation of a user name or email address.""" |
371 f = user.find(b'@') |
379 f = user.find(b'@') |