11from collections import OrderedDict
2+ from functools import total_ordering
23
34from .compat import iteritems , itervalues
4- from .definition import BasePattern
5+ from .definition import BasePatternRule
56from .parse_utils import (EMPTY_PARSED_PIECE , MIXED_RULE_SET , PieceParser ,
67 digest , parse_pattern_path_string , parse_url )
78from .parsed_piece_view import (BaseView , FuzzyView , LastDotSplitFuzzyView ,
1112from .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+
1446class _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):
83115class 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
133168class 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
212259class 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