Skip to content

Commit be99551

Browse files
committed
best match pattern
1 parent ae284fb commit be99551

4 files changed

Lines changed: 64 additions & 20 deletions

File tree

src/os_urlpattern/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.2
1+
0.1.3

src/os_urlpattern/cmdline.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
IrregularURLException)
1616
from .formatter import FORMATTERS
1717
from .pattern_maker import PatternMaker
18-
from .pattern_matcher import PatternMatcher, most_matched
18+
from .pattern_matcher import PatternMatcher
1919
from .utils import LogSpeedAdapter, load_obj, pretty_counter
2020

2121

@@ -190,8 +190,10 @@ def _match_result(self, pattern_matcher, raw_url, args):
190190
url = raw_url.decode(DEFAULT_ENCODING)
191191
result = pattern_matcher.match(url)
192192
if not args.all_matched:
193-
result = most_matched(result)
194-
result = ", ".join([r.info['ptn'] for r in result])
193+
sorted(result, reverse=True)
194+
result = result[:1]
195+
result = "\t".join([r.info['ptn']
196+
for r in result]).encode(DEFAULT_ENCODING)
195197
except (InvalidPatternException,
196198
IrregularURLException,
197199
InvalidCharException,

src/os_urlpattern/pattern.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ def __hash__(self):
7575
return hash(self.pattern_string)
7676

7777
def __eq__(self, o):
78-
if not isinstance(o, Pattern):
79-
return False
8078
return self.pattern_string == o.pattern_string
8179

8280
def match(self, piece):

src/os_urlpattern/pattern_matcher.py

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from collections import OrderedDict
2+
from functools import total_ordering
23

34
from .compat import iteritems, itervalues
4-
from .definition import BasePattern
5+
from .definition import BasePatternRule
56
from .parse_utils import (EMPTY_PARSED_PIECE, MIXED_RULE_SET, PieceParser,
67
digest, parse_pattern_path_string, parse_url)
78
from .parsed_piece_view import (BaseView, FuzzyView, LastDotSplitFuzzyView,
@@ -11,6 +12,37 @@
1112
from .pattern_tree import PatternTree
1213

1314

15+
@total_ordering
16+
class MatchPattern(Pattern):
17+
def __init__(self, pattern_string, is_last_path=False):
18+
super(MatchPattern, self).__init__(pattern_string)
19+
self._view_cls = view_cls_from_pattern(self, is_last_path)
20+
self._cmp_key = None
21+
22+
@property
23+
def cmp_key(self):
24+
if self._cmp_key is None:
25+
l = [MatchPattern(u.pattern_unit_string)
26+
for u in self.pattern_units[::-1]]
27+
self._cmp_key = ''.join([str(VIEW_ORDER[p.view_cls]) for p in l])
28+
return self._cmp_key
29+
30+
@property
31+
def view_cls(self):
32+
return self._view_cls
33+
34+
def __ne__(self, other):
35+
return self._pattern_string != other.pattern_string
36+
37+
def __lt__(self, other):
38+
if self.view_cls == other.view_cls:
39+
return self.cmp_key > other.cmp_key
40+
return VIEW_ORDER[self.view_cls] > VIEW_ORDER[other.view_cls]
41+
42+
43+
EMPTY_MATCH_PATTERN = MatchPattern(BasePatternRule.EMPTY)
44+
45+
1446
class _ViewMatcher(object):
1547
def __init__(self, view_cls):
1648
self._view_cls = view_cls
@@ -44,8 +76,8 @@ def add_match_node(self, match_node):
4476
r = fuzzy_view([u.fuzzy_rule for u in pattern.pattern_units])
4577
if r not in self._nodes:
4678
self._nodes[r] = PatternMathchTree()
47-
patterns = [BasePattern.EMPTY, ]
48-
patterns.extend([Pattern(p.pattern_unit_string)
79+
patterns = [EMPTY_MATCH_PATTERN, ]
80+
patterns.extend([MatchPattern(p.pattern_unit_string)
4981
for p in pattern.pattern_units])
5082
self._nodes[r].load_from_patterns(patterns, match_node)
5183

@@ -83,10 +115,10 @@ def match(self, parsed_piece):
83115
class MixedPatternViewMatcher(ViewMatcher):
84116

85117
def _pattern(self, pattern_units):
86-
return Pattern(u''.join([p.pattern_unit_string for p in pattern_units]))
118+
return MatchPattern(u''.join([p.pattern_unit_string for p in pattern_units]))
87119

88120
def add_match_node(self, match_node):
89-
patterns = [BasePattern.EMPTY]
121+
patterns = [EMPTY_MATCH_PATTERN]
90122
t = []
91123
for pattern_unit in match_node.pattern.pattern_units:
92124
if not pattern_unit.is_literal() \
@@ -129,9 +161,11 @@ def match(self, parsed_piece):
129161
(FuzzyView, FuzzyPatternViewMatcher),
130162
]
131163

164+
VIEW_ORDER = dict([(item[0], idx) for idx, item in enumerate(VIEW_MATCHERS)])
165+
132166

167+
@total_ordering
133168
class PatternMatchNode(object):
134-
__slot__ = ()
135169

136170
def __init__(self, pattern, info=None):
137171
self._pattern = pattern
@@ -141,6 +175,10 @@ def __init__(self, pattern, info=None):
141175
self._view_matchers = OrderedDict([(view_cls, matcher_cls(view_cls))
142176
for view_cls, matcher_cls in VIEW_MATCHERS])
143177

178+
@property
179+
def view_cls(self):
180+
return self._pattern.view_cls
181+
144182
def leaf(self):
145183
return len(self._children) == 0
146184

@@ -203,16 +241,25 @@ def add_child(self, pattern, info=None):
203241
child = PatternMatchNode(pattern, info)
204242
child.parrent = self
205243
self._children[pattern] = child
206-
view_cls = view_cls_from_pattern(pattern)
207-
self._view_matchers[view_cls].add_match_node(child)
244+
self._view_matchers[child.view_cls].add_match_node(child)
208245

209246
return self._children[pattern]
210247

248+
def __lt__(self, other):
249+
if id(self) == id(other) or self.parrent is None:
250+
return False
251+
if self.pattern == other.pattern:
252+
return self.parrent < other.parrent
253+
if self.view_cls == other.view_cls \
254+
and self.pattern.cmp_key == other.pattern.cmp_key:
255+
return self.parrent < other.parrent
256+
return self.pattern < other.pattern
257+
211258

212259
class PatternMathchTree(object):
213260

214261
def __init__(self):
215-
self._root = PatternMatchNode(BasePattern.EMPTY)
262+
self._root = PatternMatchNode(EMPTY_MATCH_PATTERN)
216263

217264
def load_from_patterns(self, patterns, info):
218265
node = self._root
@@ -241,7 +288,8 @@ def __init__(self):
241288

242289
def load(self, pattern_path_string, info=None):
243290
meta, pattern_strings = parse_pattern_path_string(pattern_path_string)
244-
patterns = [Pattern(p) for p in pattern_strings]
291+
patterns = [MatchPattern(p, idx + 1 == meta.path_depth)
292+
for idx, p in enumerate(pattern_strings)]
245293
sid = digest(meta, [p.fuzzy_rule for p in patterns])
246294
if sid not in self._pattern_match_trees:
247295
self._pattern_match_trees[sid] = PatternMathchTree()
@@ -259,7 +307,3 @@ def match(self, url):
259307
if sid in self._pattern_match_trees:
260308
return self._pattern_match_trees[sid].match(parsed_pieces)
261309
return []
262-
263-
264-
def most_matched(matched_nodes):
265-
return matched_nodes[0:1]

0 commit comments

Comments
 (0)