glob.py 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import re
  2. def translate(pattern):
  3. return match_dirs(translate_core(pattern))
  4. def match_dirs(pattern):
  5. """
  6. Ensure that zipfile.Path directory names are matched.
  7. zipfile.Path directory names always end in a slash.
  8. """
  9. return rf'{pattern}[/]?'
  10. def translate_core(pattern):
  11. r"""
  12. Given a glob pattern, produce a regex that matches it.
  13. >>> translate('*.txt')
  14. '[^/]*\\.txt'
  15. >>> translate('a?txt')
  16. 'a.txt'
  17. >>> translate('**/*')
  18. '.*/[^/]*'
  19. """
  20. return ''.join(map(replace, separate(pattern)))
  21. def separate(pattern):
  22. """
  23. Separate out character sets to avoid translating their contents.
  24. >>> [m.group(0) for m in separate('*.txt')]
  25. ['*.txt']
  26. >>> [m.group(0) for m in separate('a[?]txt')]
  27. ['a', '[?]', 'txt']
  28. """
  29. return re.finditer(r'([^\[]+)|(?P<set>[\[].*?[\]])|([\[][^\]]*$)', pattern)
  30. def replace(match):
  31. """
  32. Perform the replacements for a match from :func:`separate`.
  33. """
  34. return match.group('set') or (
  35. re.escape(match.group(0))
  36. .replace('\\*\\*', r'.*')
  37. .replace('\\*', r'[^/]*')
  38. .replace('\\?', r'.')
  39. )