annotate cutils/util/fnmatch.py @ 304:dc1f08937621

FIX: fnmatch: handle None fnmatch filter definitions
author Franz Glasner <fzglas.hg@dom66.de>
date Wed, 05 Mar 2025 10:24:51 +0100
parents bf88323d6bf7
children 6c212e407524
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
300
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1 # -*- coding: utf-8 -*-
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
2 # :-
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
3 # :Copyright: (c) 2020-2025 Franz Glasner
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
4 # :License: BSD-3-Clause
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
5 # :-
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
6 r"""File name matching.
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
7
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
8 """
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
9
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
10 from __future__ import print_function, absolute_import
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
11
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
12
302
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
13 __all__ = ["FnMatcher"]
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
14
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
15
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
16 import re
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
17
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
18 from . import glob
300
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
19
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
20
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
21 HELP_DESCRIPTION = """\
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
22 PATTERNs
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
23 ========
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
24
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
25 glob: case-sensitive, anchored at the begin and end
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
26 iglob: case-insensitive variant of "glob"
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
27 re: regular expression
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
28 path: plain text example (rooted), can be a file or a directory or a prefix
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
29 thereof
302
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
30 fullpath: exactly a single full path (file or directory), relative to the
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
31 root of the tree
300
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
32
1fc117f5f9a1 treesum: Implement --include/--exclude commandline parsing for file name inclusion and exclusion.
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
33 """
302
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
34
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
35
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
36 def glob_factory(pattern):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
37
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
38 cpat = re.compile(
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
39 # automatically anchored
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
40 "\\A{}\\Z".format(glob.glob_to_regexp(pattern)),
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
41 re.DOTALL)
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
42
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
43 def _glob_matcher(s):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
44 return cpat.search(s) is not None
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
45
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
46 return _glob_matcher
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
47
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
48
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
49 def iglob_factory(pattern):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
50
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
51 cpat = re.compile(
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
52 # automatically anchored
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
53 "\\A{}\\Z".format(glob.glob_to_regexp(pattern)),
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
54 re.DOTALL | re.IGNORECASE)
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
55
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
56 def _iglob_matcher(s):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
57 return cpat.search(s) is not None
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
58
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
59 return _iglob_matcher
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
60
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
61
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
62 def re_factory(pattern):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
63
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
64 cpat = re.compile(pattern, re.DOTALL)
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
65
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
66 def _re_matcher(s):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
67 return cpat.search(s) is not None
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
68
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
69 return _re_matcher
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
70
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
71
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
72 def path_factory(pattern):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
73
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
74 def _path_matcher(s):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
75 return s.startswith(pattern)
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
76
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
77 return _path_matcher
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
78
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
79
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
80 def fullpath_factory(pattern):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
81
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
82 def _fullpath_matcher(s):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
83 return s == pattern
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
84
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
85 return _fullpath_matcher
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
86
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
87
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
88 class FnMatcher(object):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
89
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
90 _registry = {
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
91 "glob": glob_factory,
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
92 "iglob": iglob_factory,
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
93 "re": re_factory,
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
94 "path": path_factory,
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
95 "fullpath": fullpath_factory,
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
96 }
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
97
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
98 VISIT_DEFAULT = True # Overall default value for visiting
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
99
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
100 def __init__(self, matchers):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
101 super(FnMatcher, self).__init__()
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
102 self._matchers = matchers
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
103
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
104 @classmethod
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
105 def build_from_commandline_patterns(klass, filter_definitions):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
106 matchers = []
304
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
107 if filter_definitions:
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
108 for action, kpattern in filter_definitions:
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
109 kind, sep, pattern = kpattern.partition(':')
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
110 if not sep:
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
111 # use the default
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
112 kind = "glob"
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
113 pattern = kpattern
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
114 factory = klass._registry.get(kind, None)
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
115 if not factory:
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
116 raise RuntimeError("unknown pattern kind: {}".format(kind))
dc1f08937621 FIX: fnmatch: handle None fnmatch filter definitions
Franz Glasner <fzglas.hg@dom66.de>
parents: 302
diff changeset
117 matchers.append((action, kind, factory(pattern), pattern))
302
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
118 return klass(matchers)
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
119
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
120 def shall_visit(self, fn):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
121 visit = self.VISIT_DEFAULT
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
122 for action, kind, matcher, orig_pattern in self._matchers:
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
123 res = matcher(fn)
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
124 if res:
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
125 if action == "include":
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
126 visit = True
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
127 elif action == "exclude":
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
128 visit = False
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
129 else:
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
130 raise RuntimeError("unknown action: {}".format(action))
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
131 return visit
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
132
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
133 def definitions(self):
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
134 for action, kind, matcher, orig_pattern in self._matchers:
bf88323d6bf7 treesum: Implement --exclude/--include.
Franz Glasner <fzglas.hg@dom66.de>
parents: 300
diff changeset
135 yield (action, kind, orig_pattern)