374 return kind, pattern, match |
374 return kind, pattern, match |
375 |
375 |
376 raise error.ProgrammingError(b'unhandled pattern kind: %s' % kind) |
376 raise error.ProgrammingError(b'unhandled pattern kind: %s' % kind) |
377 |
377 |
378 |
378 |
|
379 def substringregexp(pattern, flags=0): |
|
380 """Build a regexp object from a string pattern possibly starting with |
|
381 're:' or 'literal:' prefix. |
|
382 |
|
383 helper for tests: |
|
384 >>> def test(pattern, *tests): |
|
385 ... regexp = substringregexp(pattern) |
|
386 ... return [bool(regexp.search(t)) for t in tests] |
|
387 >>> def itest(pattern, *tests): |
|
388 ... regexp = substringregexp(pattern, remod.I) |
|
389 ... return [bool(regexp.search(t)) for t in tests] |
|
390 |
|
391 substring matching (no prefix): |
|
392 >>> test(b'bcde', b'abc', b'def', b'abcdefg') |
|
393 [False, False, True] |
|
394 |
|
395 substring pattern should be escaped: |
|
396 >>> substringregexp(b'.bc').pattern |
|
397 '\\\\.bc' |
|
398 >>> test(b'.bc', b'abc', b'def', b'abcdefg') |
|
399 [False, False, False] |
|
400 |
|
401 regex matching ('re:' prefix) |
|
402 >>> test(b're:a.+b', b'nomatch', b'fooadef', b'fooadefbar') |
|
403 [False, False, True] |
|
404 |
|
405 force substring matches ('literal:' prefix) |
|
406 >>> test(b'literal:re:foobar', b'foobar', b're:foobar') |
|
407 [False, True] |
|
408 |
|
409 case insensitive literal matches |
|
410 >>> itest(b'BCDE', b'abc', b'def', b'abcdefg') |
|
411 [False, False, True] |
|
412 |
|
413 case insensitive regex matches |
|
414 >>> itest(b're:A.+b', b'nomatch', b'fooadef', b'fooadefBar') |
|
415 [False, False, True] |
|
416 """ |
|
417 kind, pattern = _splitpattern(pattern) |
|
418 if kind == b're': |
|
419 try: |
|
420 return remod.compile(pattern, flags) |
|
421 except remod.error as e: |
|
422 raise error.ParseError( |
|
423 _(b'invalid regular expression: %s') % forcebytestr(e) |
|
424 ) |
|
425 elif kind == b'literal': |
|
426 return remod.compile(remod.escape(pattern), flags) |
|
427 |
|
428 raise error.ProgrammingError(b'unhandled pattern kind: %s' % kind) |
|
429 |
|
430 |
379 def shortuser(user): |
431 def shortuser(user): |
380 """Return a short representation of a user name or email address.""" |
432 """Return a short representation of a user name or email address.""" |
381 f = user.find(b'@') |
433 f = user.find(b'@') |
382 if f >= 0: |
434 if f >= 0: |
383 user = user[:f] |
435 user = user[:f] |