Advertisement
Guest User

Untitled

a guest
Sep 20th, 2017
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.19 KB | None | 0 0
  1.  
  2. def get_words(camel_cased):
  3.     """Split CamelCasedWord to list of Capitalized words, with special asterisk (*) case, where it have own list element.
  4.  
  5.    For example: AbraKadabra*PoraMora -> ['Abra','Kadabra','*','Pora','Mora']
  6.    """
  7.     if not camel_cased:
  8.         return []
  9.  
  10.     for i, let in enumerate(camel_cased[0:]):
  11.         is_capital = ord("A") <= ord(let) <= ord("Z") or let == "*"
  12.         if is_capital and i > 0:
  13.             first_word, other_words = camel_cased[:i], get_words(camel_cased[i:])
  14.             return [first_word] + other_words
  15.     return [camel_cased]
  16.  
  17. class ClassMatcher(object):
  18.     """Class matcher, that could find classes from the list provided in constructor. For find matches use
  19.        method "find_matching".
  20.  
  21.        There list of rules, that you can search with:
  22.            1. Pattern contains Capital letters, that represents Capital letters
  23.                in class name in original order.
  24.                Example: "FB" will match with "FooBarBaz" and "FooBar"
  25.            2. Between Capital letters could be small letters, than appears in
  26.                class name between same capital letter with same order.
  27.                Example: "FoBa" and "FBar" will match with "FooBarBaz" and "FooBar"
  28.            3. If pattern ends with space, than it's last "word" (Capital letter with optional small letters)
  29.                should be the last word in class name.
  30.                Example: "FBar " will match with "FooBar", but not "FooBarBaz"
  31.            4. Pattern can contain asterisks (*), that matches any words.
  32.                Example: "F*Baz" and "*BB" will match with "FooBarBaz"
  33.    """
  34.  
  35.     def __init__(self, classes):
  36.         self.classes = map(ProcessedClass, classes)
  37.         self.pattern_words = []
  38.         self.curr_patt_word_index = None
  39.         self.next_asterisk_pos = None
  40.  
  41.  
  42.     def find_matching(self, pattern):
  43.         """Finds all classes which match given pattern.
  44.  
  45.        Arguments:
  46.            pattern String representation of pattern to match classes
  47.  
  48.        Returns:
  49.            sorted alphabetically list of match classes.
  50.        """
  51.         classes = self.classes
  52.  
  53.         self.pattern_words = get_words(pattern)
  54.         for patt_word_index in range(len(self.pattern_words)):
  55.             #Each pattern word is apply to classes. Those classes left that satisfy condition.
  56.             self.curr_patt_word_index = patt_word_index
  57.             next_position = patt_word_index + 1
  58.             self.next_asterisk_pos = self.get_next_asterisk_pos(next_position, self.pattern_words)
  59.             classification_filter = lambda clazz: self.is_class_matches_pattern(clazz)
  60.             classes = filter(classification_filter, classes)
  61.  
  62.         self.restore_classes()
  63.         return self.get_sorted_classes_fullnames(classes)
  64.  
  65.     def restore_classes(self):
  66.         [clazz.restore() for clazz in self.classes]
  67.  
  68.     def get_sorted_classes_fullnames(self, classes):
  69.         classes.sort(key=lambda clazz: clazz.class_name)
  70.         return map(lambda clazz: clazz.full_name, classes)
  71.  
  72.     def get_next_asterisk_pos(self, starting_from, words):
  73.         """Find closest asterisk (*) element in array starting from some index.
  74.        """
  75.         following_words = words[starting_from:]
  76.         return words.index("*", starting_from) if "*" in following_words else None
  77.  
  78.     def is_class_matches_pattern(self, clazz):
  79.         """Checking if given class is matching with any pattern word defined with list of all pattern words and index.
  80.        """
  81.         pattern_word = self.pattern_words[self.curr_patt_word_index]
  82.         class_words = clazz.words
  83.         class_words_length = len(class_words)
  84.  
  85.         if self.curr_patt_word_index >= class_words_length:
  86.             return False
  87.  
  88.         if pattern_word == "*":
  89.             return self.is_class_matches_asterisk_pattern(clazz)
  90.  
  91.         if not class_words[self.curr_patt_word_index].startswith(pattern_word.strip()):
  92.             return False
  93.  
  94.         if pattern_word[-1] == " ":
  95.             return self.curr_patt_word_index + 1 == class_words_length
  96.  
  97.         return True
  98.  
  99.     def is_class_matches_asterisk_pattern(self, clazz):
  100.         """Checking if given class is matching with wildcard pattern word defined with list of all pattern words and index.
  101.        """
  102.         should_be_words = self.pattern_words[self.curr_patt_word_index + 1:self.next_asterisk_pos]
  103.         if not should_be_words:
  104.             return True
  105.  
  106.         new_class_words = self.find_n_replace_asterisk_match(clazz.words, should_be_words, self.curr_patt_word_index)
  107.         if new_class_words:
  108.             clazz.words = new_class_words
  109.             return True
  110.  
  111.     def find_last_asterisk_match(self, class_words, starting_from, words_sequence):
  112.         i = 0
  113.         last_pos = None
  114.         find_last = words_sequence[-1][-1] == " "
  115.         for class_word_index in range(starting_from, len(class_words)):
  116.             if class_words[class_word_index].startswith(words_sequence[i].strip()):
  117.                 i += 1
  118.             else:
  119.                 i = 0
  120.  
  121.             if i == len(words_sequence):
  122.                 last_pos = class_word_index
  123.                 if not find_last:
  124.                     break
  125.                 i = 0
  126.         return last_pos
  127.  
  128.     def replace_matched_area(self, class_words, starting_from, last_match_start_pos):
  129.         return class_words[:starting_from] + ["*"] + class_words[last_match_start_pos:]
  130.  
  131.     def find_n_replace_asterisk_match(self, class_words, words_sequence, starting_from):
  132.         """Searching for matching continues words sequence in the class words starting from some index.
  133.        """
  134.         last_position = self.find_last_asterisk_match(class_words, starting_from, words_sequence)
  135.  
  136.         if last_position is None:
  137.             return None
  138.  
  139.         last_match_start_pos = last_position - len(words_sequence) + 1
  140.         return  self.replace_matched_area(class_words, starting_from, last_match_start_pos)
  141.  
  142. class ProcessedClass(object):
  143.     """A bit preprocessed representation of class name
  144.    """
  145.     def __init__(self, clazz):
  146.         self.full_name = clazz
  147.         self.class_name = clazz[clazz.rfind(".")+1:]
  148.         self.words = get_words(self.class_name)
  149.         self.orig_words = self.words[:]
  150.  
  151.     def __repr__(self):
  152.         return self.full_name
  153.  
  154.     def restore(self):
  155.         self.words = self.orig_words
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement