Robot Framework Integrated Development Environment (RIDE)
tagstatistics.py
Go to the documentation of this file.
1 # Copyright 2008-2015 Nokia Networks
2 # Copyright 2016- Robot Framework Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 from itertools import chain
17 import re
18 
19 from robotide.lib.robot.utils import NormalizedDict, unicode
20 
21 from .stats import CombinedTagStat, CriticalTagStat, TagStat
22 from .tags import SingleTagPattern, TagPatterns
23 
24 
25 
26 class TagStatistics():
27 
28  def __init__(self, critical_stats, non_critical_stats, combined_stats):
29  #: Dictionary, where key is the name of the tag as a string and value
30  #: is an instance of :class:`~robot.model.stats.TagStat`.
31  self.tagstags = NormalizedDict(ignore='_')
32  #: List of :class:`~robot.model.stats.CriticalTagStat` objects.
33  self.criticalcritical = critical_stats
34  #: List of :class:`~robot.model.stats.CriticalTagStat` objects.
35  self.non_criticalnon_critical = non_critical_stats
36  #: List of :class:`~robot.model.stats.CombinedTagStat` objects.
37  self.combinedcombined = combined_stats
38 
39  def visit(self, visitor):
40  visitor.visit_tag_statistics(self)
41 
42  def __iter__(self):
43  crits = self._get_critical_and_non_critical_matcher_get_critical_and_non_critical_matcher()
44  tags = [t for t in self.tagstags.values() if t.name not in crits]
45  return iter(sorted(chain(self.criticalcritical, self.non_criticalnon_critical,
46  self.combinedcombined, tags)))
47 
49  crits = [stat for stat in self.criticalcritical + self.non_criticalnon_critical
50  if isinstance(stat.pattern, SingleTagPattern)]
51  return NormalizedDict([(unicode(stat.pattern), None) for stat in crits],
52  ignore='_')
53 
54 
56 
57  def __init__(self, criticality=None, included=None, excluded=None,
58  combined=None, docs=None, links=None):
59  self._included_included = TagPatterns(included)
60  self._excluded_excluded = TagPatterns(excluded)
61  self._info_info = TagStatInfo(docs, links)
62  self.statsstats = TagStatistics(
63  self._info_info.get_critical_stats(criticality),
64  self._info_info.get_critical_stats(criticality, critical=False),
65  self._info_info.get_combined_stats(combined)
66  )
67 
68  def add_test(self, test):
69  self._add_tags_to_statistics_add_tags_to_statistics(test)
70  self._add_to_critical_and_combined_statistics_add_to_critical_and_combined_statistics(test)
71 
72  def _add_tags_to_statistics(self, test):
73  for tag in test.tags:
74  if self._is_included_is_included(tag):
75  if tag not in self.statsstats.tags:
76  self.statsstats.tags[tag] = self._info_info.get_stat(tag)
77  self.statsstats.tags[tag].add_test(test)
78 
79  def _is_included(self, tag):
80  if self._included_included and not self._included_included.match(tag):
81  return False
82  return not self._excluded_excluded.match(tag)
83 
85  stats = self.statsstats
86  for stat in stats.critical + stats.non_critical + stats.combined:
87  if stat.match(test.tags):
88  stat.add_test(test)
89 
90 
91 class TagStatInfo():
92 
93  def __init__(self, docs=None, links=None):
94  self._docs_docs = [TagStatDoc(*doc) for doc in docs or []]
95  self._links_links = [TagStatLink(*link) for link in links or []]
96 
97  def get_stat(self, tag):
98  return TagStat(tag, self.get_docget_doc(tag), self.get_linksget_links(tag))
99 
100  def get_critical_stats(self, criticality, critical=True):
101  if not criticality:
102  return []
103  tag_patterns = (criticality.critical_tags
104  if critical else criticality.non_critical_tags)
105  return [self._get_critical_stat_get_critical_stat(p, critical) for p in tag_patterns]
106 
107  def _get_critical_stat(self, pattern, critical):
108  name = unicode(pattern)
109  return CriticalTagStat(pattern, name, critical, self.get_docget_doc(name),
110  self.get_linksget_links(name))
111 
112  def get_combined_stats(self, combined=None):
113  return [self._get_combined_stat_get_combined_stat(*comb) for comb in combined or []]
114 
115  def _get_combined_stat(self, pattern, name=None):
116  name = name or pattern
117  return CombinedTagStat(pattern, name, self.get_docget_doc(name),
118  self.get_linksget_links(name))
119 
120  def get_doc(self, tag):
121  return ' & '.join(doc.text for doc in self._docs_docs if doc.match(tag))
122 
123  def get_links(self, tag):
124  return [link.get_link(tag) for link in self._links_links if link.match(tag)]
125 
126 
127 class TagStatDoc():
128 
129  def __init__(self, pattern, doc):
130  self._matcher_matcher = TagPatterns(pattern)
131  self.texttext = doc
132 
133  def match(self, tag):
134  return self._matcher_matcher.match(tag)
135 
136 
137 class TagStatLink():
138 
141  _match_pattern_tokenizer = re.compile('(\*|\?+)')
142 
143  def __init__(self, pattern, link, title):
144  self._regexp_regexp = self._get_match_regexp_get_match_regexp(pattern)
145  self._link_link = link
146  self._title_title = title.replace('_', ' ')
147 
148  def match(self, tag):
149  return self._regexp_regexp.match(tag) is not None
150 
151  def get_link(self, tag):
152  match = self._regexp_regexp.match(tag)
153  if not match:
154  return None
155  link, title = self._replace_groups_replace_groups(self._link_link, self._title_title, match)
156  return link, title
157 
158  def _replace_groups(self, link, title, match):
159  for index, group in enumerate(match.groups()):
160  placefolder = '%%%d' % (index+1)
161  link = link.replace(placefolder, group)
162  title = title.replace(placefolder, group)
163  return link, title
164 
165  def _get_match_regexp(self, pattern):
166  pattern = '^%s$' % ''.join(self._yield_match_pattern_yield_match_pattern(pattern))
167  return re.compile(pattern, re.IGNORECASE)
168 
169  def _yield_match_pattern(self, pattern):
170  for token in self._match_pattern_tokenizer_match_pattern_tokenizer.split(pattern):
171  if token.startswith('?'):
172  yield '(%s)' % ('.'*len(token))
173  elif token == '*':
174  yield '(.*)'
175  else:
176  yield re.escape(token)
Stores statistic values for a single tag.
Definition: stats.py:130
def _get_combined_stat(self, pattern, name=None)
def __init__(self, docs=None, links=None)
def get_critical_stats(self, criticality, critical=True)
def __init__(self, criticality=None, included=None, excluded=None, combined=None, docs=None, links=None)
def __init__(self, critical_stats, non_critical_stats, combined_stats)
unicode
Exceptions and return codes used internally.
Definition: errors.py:24