Robot Framework
suitestructure.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 import os.path
17 
18 from robot.errors import DataError
19 from robot.model import SuiteNamePatterns
20 from robot.output import LOGGER
21 from robot.utils import abspath, get_error_message, safe_str
22 
23 
25 
26  def __init__(self, source=None, init_file=None, children=None):
27  self.sourcesource = source
28  self.init_fileinit_file = init_file
29  self.childrenchildren = children
30  self.extensionextension = self._get_extension_get_extension(source, init_file)
31 
32  def _get_extension(self, source, init_file):
33  if self.is_directoryis_directoryis_directory and not init_file:
34  return None
35  source = init_file or source
36  return os.path.splitext(source)[1][1:].lower()
37 
38  @property
39  is_directory = property
40 
41  def is_directory(self):
42  return self.childrenchildren is not None
43 
44  def visit(self, visitor):
45  if self.childrenchildren is None:
46  visitor.visit_file(self)
47  else:
48  visitor.visit_directory(self)
49 
50 
52  ignored_prefixes = ('_', '.')
53  ignored_dirs = ('CVS',)
54 
55  def __init__(self, included_extensions=('robot',), included_suites=None):
56  self.included_extensionsincluded_extensions = included_extensions
57  self.included_suitesincluded_suites = included_suites
58 
59  def build(self, paths):
60  paths = list(self._normalize_paths_normalize_paths(paths))
61  if len(paths) == 1:
62  return self._build_build(paths[0], self.included_suitesincluded_suites)
63  children = [self._build_build(p, self.included_suitesincluded_suites) for p in paths]
64  return SuiteStructure(children=children)
65 
66  def _normalize_paths(self, paths):
67  if not paths:
68  raise DataError('One or more source paths required.')
69  for path in paths:
70  path = os.path.normpath(path)
71  if not os.path.exists(path):
72  raise DataError("Parsing '%s' failed: File or directory to "
73  "execute does not exist." % path)
74  yield abspath(path)
75 
76  def _build(self, path, include_suites):
77  if os.path.isfile(path):
78  return SuiteStructure(path)
79  include_suites = self._get_include_suites_get_include_suites(path, include_suites)
80  init_file, paths = self._get_child_paths_get_child_paths(path, include_suites)
81  children = [self._build_build(p, include_suites) for p in paths]
82  return SuiteStructure(path, init_file, children)
83 
84  def _get_include_suites(self, path, incl_suites):
85  if not incl_suites:
86  return None
87  if not isinstance(incl_suites, SuiteNamePatterns):
88  incl_suites = SuiteNamePatterns(
89  self._create_included_suites_create_included_suites(incl_suites))
90  # If a directory is included, also all its children should be included.
91  if self._is_in_included_suites_is_in_included_suites(os.path.basename(path), incl_suites):
92  return None
93  return incl_suites
94 
95  def _create_included_suites(self, incl_suites):
96  for suite in incl_suites:
97  yield suite
98  while '.' in suite:
99  suite = suite.split('.', 1)[1]
100  yield suite
101 
102  def _get_child_paths(self, dirpath, incl_suites=None):
103  init_file = None
104  paths = []
105  for path, is_init_file in self._list_dir_list_dir(dirpath, incl_suites):
106  if is_init_file:
107  if not init_file:
108  init_file = path
109  else:
110  LOGGER.error("Ignoring second test suite init file '%s'."
111  % path)
112  else:
113  paths.append(path)
114  return init_file, paths
115 
116  def _list_dir(self, dir_path, incl_suites):
117  try:
118  names = os.listdir(dir_path)
119  except:
120  raise DataError("Reading directory '%s' failed: %s"
121  % (dir_path, get_error_message()))
122  for name in sorted(names, key=lambda item: item.lower()):
123  name = safe_str(name) # Handles NFC normalization on OSX
124  path = os.path.join(dir_path, name)
125  base, ext = os.path.splitext(name)
126  ext = ext[1:].lower()
127  if self._is_init_file_is_init_file(path, base, ext):
128  yield path, True
129  elif self._is_included_is_included(path, base, ext, incl_suites):
130  yield path, False
131  else:
132  LOGGER.info("Ignoring file or directory '%s'." % path)
133 
134  def _is_init_file(self, path, base, ext):
135  return (base.lower() == '__init__'
136  and ext in self.included_extensionsincluded_extensions
137  and os.path.isfile(path))
138 
139  def _is_included(self, path, base, ext, incl_suites):
140  if base.startswith(self.ignored_prefixesignored_prefixes):
141  return False
142  if os.path.isdir(path):
143  return base not in self.ignored_dirsignored_dirs or ext
144  if ext not in self.included_extensionsincluded_extensions:
145  return False
146  return self._is_in_included_suites_is_in_included_suites(base, incl_suites)
147 
148  def _is_in_included_suites(self, name, incl_suites):
149  if not incl_suites:
150  return True
151  return incl_suites.match(self._split_prefix_split_prefix(name))
152 
153  def _split_prefix(self, name):
154  result = name.split('__', 1)[-1]
155  if result:
156  return result
157  return name
158 
159 
161 
162  def visit_file(self, structure):
163  pass
164 
165  def visit_directory(self, structure):
166  self.start_directory(structure)
167  for child in structure.children:
168  child.visit(self)
169  self.end_directory(structure)
170 
171  def start_directory(self, structure):
172  pass
173 
174  def end_directory(self, structure):
175  pass
def _is_included(self, path, base, ext, incl_suites)
def _list_dir(self, dir_path, incl_suites)
def _is_in_included_suites(self, name, incl_suites)
def _get_child_paths(self, dirpath, incl_suites=None)
def __init__(self, included_extensions=('robot',), included_suites=None)
def _get_include_suites(self, path, incl_suites)
def __init__(self, source=None, init_file=None, children=None)
def _get_extension(self, source, init_file)
def get_error_message()
Returns error message of the last occurred exception.
Definition: error.py:34
def abspath(path, case_normalize=False)
Replacement for os.path.abspath with some enhancements and bug fixes.
Definition: robotpath.py:65
def safe_str(item)
Definition: unic.py:21