def write_file_data(self, file_or_path, offset=0, length=-1, port_locator=None): """ Writes content of file into the port. File can be specified by file path or opened file-like object. In former case, path should be absolute or relative to current directory. In latter case, file (or file-like object should support read with specified length. If offset is non-zero, file is seek()-ed from *current position* (not the beginning of the file). Note that your the file object should support seek() method with SEEK_CUR. If length is negative, all content after current input file position is read. Otherwise, number of specified bytes are read from the input file. Fails if specified file could not be opened. """ infile = file_or_path if is_string(file_or_path): infile = open(file_or_path, 'rb') if is_string(offset): offset = int(offset) if is_string(length): length = int(length) if offset > 0: infile.seek(offset, SEEK_CUR) read_bytes = infile.read(length) if length >= 0 else infile.read() self._port(port_locator).write(read_bytes)
def TestSuiteFactory(datasources, **options): settings = RobotSettings(options) if is_string(datasources): datasources = [datasources] suite = TestSuiteBuilder().build(*datasources) suite.configure(**settings.suite_config) return suite
def _import_listener(self, listener): if not is_string(listener): return listener, type_name(listener) name, args = split_args_from_name_or_path(listener) importer = Importer("listener") listener = importer.import_class_or_module(os.path.normpath(name), instantiate_with_args=args) return listener, name
def replace_string(self, string, ignore_errors=False): """Replaces variables from a string. Result is always a string.""" if not is_string(string): return unic(string) if self._cannot_have_variables(string): return unescape(string) return self._replace_string(string, ignore_errors=ignore_errors)
def is_truthy_on_off(item): if is_string(item): item = item.strip() if item.isdigit(): return bool(int(item)) return item.strip().upper() not in ['FALSE', 'NO', '0', 'OFF', ''] return bool(item)
def _format_values(self, values): separator = None if is_string(values): values = [values] elif values and values[0].startswith("SEPARATOR="): separator = values.pop(0)[10:] return separator, values
def _get_matches_in_iterable(iterable, pattern, case_insensitive=False, whitespace_insensitive=False): if not is_string(pattern): raise TypeError("Pattern must be string, got '%s'." % type_name(pattern)) regexp = False if pattern.startswith('regexp='): pattern = pattern[7:] regexp = True elif pattern.startswith('glob='): pattern = pattern[5:] matcher = Matcher(pattern, caseless=is_truthy(case_insensitive), spaceless=is_truthy(whitespace_insensitive), regexp=regexp) return [string for string in iterable if is_string(string) and matcher.match(string)]
def is_var(string, identifiers='$@&'): if not string or not is_string(string) or len(string) < 4: return False if string[0] not in identifiers or string[1] != '{' or string[-1] != '}': return False body = string[2:-1] return '{' not in body and '}' not in body
def _write_file(self, path, config, template): outfile = file_writer(path) \ if is_string(path) else path # unit test hook with outfile: model_writer = RobotModelWriter(outfile, self._js_model, config) writer = HtmlFileWriter(outfile, model_writer) writer.write(template)
def log_java_system_properties(self): """Log and return java properties and environment information from the current java application. """ env = self._run_from_services('getEnvironment') logger.info(env) if IS_PYTHON3 and not is_string(env): return env.decode('utf-8') return env
def _format_values(self, values): separator = None if is_string(values): values = [values] elif values and values[0].startswith('SEPARATOR='): separator = values[0][10:] values = values[1:] return separator, values
def _convert_date_to_seconds(self, date, input_format): if is_string(date): return self._string_to_epoch(date, input_format) elif isinstance(date, datetime): return self._mktime_with_millis(date) elif is_number(date): return float(date) raise ValueError("Unsupported input '%s'." % date)
def is_var(string, identifiers='$@&'): if not is_string(string): return False length = len(string) return (length > 3 and string[0] in identifiers and string.rfind('{') == 1 and string.find('}') == length - 1)
def _convert_to_datetime(self, date, input_format): if isinstance(date, datetime): return date if is_number(date): return self._seconds_to_datetime(date) if is_string(date): return self._string_to_datetime(date, input_format) raise ValueError("Unsupported input '%s'." % date)
def should_not_be_string(self, item, msg=None): """Fails if the given ``item`` is a string. The default error message can be overridden with the optional ``msg`` argument. """ if is_string(item): self._fail(msg, "'%s' is a string.", item)
def get_library(self, name_or_instance): try: if is_string(name_or_instance): return self.libraries[name_or_instance.replace(' ', '')] else: return self._get_lib_by_instance(name_or_instance) except KeyError: raise DataError("No library '%s' found." % name_or_instance)
def convert_to_title_case(self, string, exclude=None): """Converts string to title case. Uses the following algorithm: - Split the string to words from whitespace characters (spaces, newlines, etc.). - Exclude words that are not all lower case. This preserves, for example, "OK" and "iPhone". - Exclude also words listed in the optional ``exclude`` argument. - Title case the first alphabetical character of each word that has not been excluded. - Join all words together so that original whitespace is preserved. Explicitly excluded words can be given as a list or as a string with words separated by a comma and an optional space. Excluded words are actually considered to be regular expression patterns, so it is possible to use something like "example[.!?]?" to match the word "example" on it own and also if followed by ".", "!" or "?". See `BuiltIn.Should Match Regexp` for more information about Python regular expression syntax in general and how to use it in Robot Framework test data in particular. Examples: | ${str1} = | Convert To Title Case | hello, world! | | ${str2} = | Convert To Title Case | it's an OK iPhone | exclude=a, an, the | | ${str3} = | Convert To Title Case | distance is 1 km. | exclude=is, km.? | | Should Be Equal | ${str1} | Hello, World! | | Should Be Equal | ${str2} | It's an OK iPhone | | Should Be Equal | ${str3} | Distance is 1 km. | The reason this keyword does not use Python's standard [https://docs.python.org/library/stdtypes.html#str.title|title()] method is that it can yield undesired results, for example, if strings contain upper case letters or special characters like apostrophes. It would, for example, convert "it's an OK iPhone" to "It'S An Ok Iphone". New in Robot Framework 3.2. """ if is_string(exclude): exclude = [e.strip() for e in exclude.split(',')] elif not exclude: exclude = [] exclude = [re.compile('^%s$' % e) for e in exclude] def title(word): if any(e.match(word) for e in exclude) or not word.islower(): return word for index, char in enumerate(word): if char.isalpha(): return word[:index] + word[index].title() + word[index + 1:] return word tokens = re.split(r'(\s+)', string, flags=re.UNICODE) return ''.join(title(token) for token in tokens)
def __init__(self, listener): if is_string(listener): name, args = split_args_from_name_or_path(listener) listener = self._import_listener(name, args) else: name = type_name(listener) self.name = name self.version = self._get_version(listener) AbstractLoggerProxy.__init__(self, listener)
def _import_listeners(self, listeners): for listener in listeners: try: yield ListenerProxy(listener) except DataError as err: if not is_string(listener): listener = type_name(listener) LOGGER.error("Taking listener '%s' into use failed: %s" % (listener, err.message))
def _convert_to_list(self, return_value): if return_value is None: return [None] * self._min_count if is_string(return_value): self._raise_expected_list(return_value) try: return list(return_value) except TypeError: self._raise_expected_list(return_value)
def __init__(self, parent, name, value, comment=None): self.parent = parent self.name = name.rstrip('= ') if name.startswith('$') and value == []: value = '' if is_string(value): value = [value] self.value = value self.comment = Comment(comment)
def is_var(string, identifiers='$@&', allow_assign_mark=False): if not is_string(string) or len(string) < 4: return False if allow_assign_mark and string[-1] == '=': string = rstrip(string[:-1]) if string[0] not in identifiers or string[1] != '{' or string[-1] != '}': return False body = string[2:-1] return '{' not in body and '}' not in body
def __setitem__(self, key, item): if not is_string(key) and not isinstance(key, tuple): raise FrameworkError('Invalid key for ImportCache') key = self._norm_path_key(key) if key not in self._keys: self._keys.append(key) self._items.append(item) else: self._items[self._keys.index(key)] = item
def coerce(self, argument, dryrun=False): if not is_string(argument) \ or (dryrun and contains_var(argument)): return argument try: return self._coerce(argument) except ValueError: raise ValueError('Argument at position %d cannot be coerced to %s.' % (self._position, self._name))
def __init__(self, log_path=None, split_log=False, prune_input=False): # log_path can be a custom object in unit tests self._log_dir = dirname(log_path) if is_string(log_path) else None self._split_log = split_log self._prune_input = prune_input self._strings = self._top_level_strings = StringCache() self.basemillis = None self.split_results = [] self.min_level = 'NONE' self._msg_links = {}
def _import_listener(self, listener): if not is_string(listener): # Modules have `__name__`, with others better to use `type_name`. name = getattr(listener, '__name__', None) or type_name(listener) return listener, name name, args = split_args_from_name_or_path(listener) importer = Importer('listener') listener = importer.import_class_or_module(os.path.normpath(name), instantiate_with_args=args) return listener, name
def _import_listeners(self, listener_data): listeners = [] for listener in listener_data: try: listeners.append(ListenerProxy(listener)) except DataError as err: if not is_string(listener): listener = type_name(listener) LOGGER.error("Taking listener '%s' into use failed: %s" % (listener, unicode(err))) return listeners
def _split_alias(self, args, parent): if len(args) > 1 and is_string(args[-2]): with_name = args[-2] if with_name.upper() == 'WITH NAME': # TODO: Require all uppercase 'WITH NAME' in RF 3.1. # https://github.com/robotframework/robotframework/issues/2263 if with_name != 'WITH NAME': self._deprecation_warning(with_name, parent) return args[:-2], args[-1] return args, None
def coerce(self, argument, dryrun=False): if not is_string(argument) \ or (dryrun and contains_var(argument)): return argument try: return self._coerce(argument) except ValueError: raise ValueError( 'Argument at position %d cannot be coerced to %s.' % (self._position, self._name))
def _parse_sequence_variable_index(self, index): if isinstance(index, (int, slice)): return index if not is_string(index): raise ValueError if ':' not in index: return int(index) if index.count(':') > 2: raise ValueError return slice(*[int(i) if i else None for i in index.split(':')])
def _import_listeners(self, listener_data): listeners = [] for listener in listener_data: try: listeners.append(ListenerProxy(listener)) except DataError as err: if not is_string(listener): listener = type_name(listener) LOGGER.error("Taking listener '%s' into use failed: %s" % (listener, err.message)) return listeners
def __init__(self, listener): if is_string(listener): name, args = split_args_from_name_or_path(listener) listener = self._import_listener(name, args) else: name = type_name(listener) AbstractLoggerProxy.__init__(self, listener) self.name = name self.version = self._get_version(listener) if self.version == 1: LOGGER.warn("Listener '%s' uses deprecated API version 1. " "Switch to API version 2 instead." % self.name)
def should_not_be_string(self, item, msg=None): """Fails if the given ``item`` is a string. See `Should Be String` for more details about Unicode strings and byte strings. The default error message can be overridden with the optional ``msg`` argument. """ if is_string(item): self._fail(msg, "'%s' is a string.", item)
def _yield_visitors(self, visitors): importer = Importer('model modifier') for visitor in visitors: try: if not is_string(visitor): yield visitor else: name, args = split_args_from_name_or_path(visitor) yield importer.import_class_or_module(name, args) except DataError as err: self._log_error(err.message)
def read_n_bytes(self, size=1, encoding=None, port_locator=None): """ Reads specified number of bytes from the port. Note that if no timeout is specified this keyword may block until the requested number of bytes is read. Returns (encoded) read data. """ if is_string(size): size = int(size) return self._decode(self._port(port_locator).read(size))
def _get_matches_in_iterable(iterable, pattern, case_insensitive=False, whitespace_insensitive=False): if not is_string(pattern): raise TypeError(f"Pattern must be string, got '{type_name(pattern)}'.") regexp = False if pattern.startswith('regexp='): pattern = pattern[7:] regexp = True elif pattern.startswith('glob='): pattern = pattern[5:] matcher = Matcher(pattern, caseless=is_truthy(case_insensitive), spaceless=is_truthy(whitespace_insensitive), regexp=regexp) return [ string for string in iterable if is_string(string) and matcher.match(string) ]
def _to_string(self, value, allow_tuple=False, allow_none=False): if is_string(value): return value if is_bytes(value): return value.decode('UTF-8') if allow_tuple and is_list_like(value) and len(value) > 0: return tuple(value) if allow_none and value is None: return value or_tuple = ' or a non-empty tuple' if allow_tuple else '' raise DataError('Return value must be a string%s, got %s.' % (or_tuple, type_name(value)))
def save_selenium_screenshot(self): """Takes a screenshot with a unique filename to be stored in Robot Framework compiled reports. If `Set Screenshot Directory` has been set to ``EMBED`` then the screenshot will be embedded into the report """ if is_string(self.screenshot_root_directory): if self.screenshot_root_directory.upper() == 'EMBED': return self.capture_page_screenshot() else: timestamp = time() filename = 'selenium-screenshot-' + str(timestamp) + '-' + str(next(SCREENSHOT_COUNTER)) + '.png' return self.capture_page_screenshot(filename)
def should_be_string(self, item, msg=None): """Fails if the given ``item`` is not a string. This keyword passes regardless is the ``item`` is a Unicode string or a byte string. Use `Should Be Unicode String` or `Should Be Byte String` if you want to restrict the string type. The default error message can be overridden with the optional ``msg`` argument. """ if not is_string(item): self._fail(msg, "'%s' is not a string.", item)
def _should_run_branch(self, condition, recursive_dry_run=False): if self._context.dry_run: return not recursive_dry_run if not self._run: return False if condition is None: return True condition = self._context.variables.replace_scalar(condition) if is_string(condition): return evaluate_expression(condition, self._context.variables.current.store) return bool(condition)
def evaluate_expression(expression, variable_store=None, modules=None, namespace=None): try: if not is_string(expression): raise TypeError("Expression must be string, got %s." % type_name(expression)) if not expression: raise ValueError("Expression cannot be empty.") return _evaluate(expression, variable_store, modules, namespace) except: raise DataError("Evaluating expression '%s' failed: %s" % (expression, get_error_message()))
def import_listeners(cls, listeners, method_names, prefix=None, raise_on_error=False): imported = [] for listener in listeners: try: imported.append(cls(listener, method_names, prefix)) except DataError as err: name = listener if is_string(listener) else type_name(listener) msg = "Taking listener '%s' into use failed: %s" % (name, err) if raise_on_error: raise DataError(msg) LOGGER.error(msg) return imported
def _get_runner(self, name): if not name: raise DataError('Keyword name cannot be empty.') if not is_string(name): raise DataError('Keyword name must be a string.') runner = self._get_runner_from_test_case_file(name) if not runner and '.' in name: runner = self._get_explicit_runner(name) if not runner: runner = self._get_implicit_runner(name) if not runner: runner = self._get_bdd_style_runner(name) return runner
def execute(expression, modules=None, namespace=None): if modules == u"None": modules = None from robot.libraries.BuiltIn import BuiltIn from robot.utils import is_string bi = BuiltIn() if is_string(expression) and '$' in expression: expression, variables = bi._handle_variables_in_expression( expression) else: variables = {} namespace = bi._create_evaluation_namespace(namespace, modules) try: if not is_string(expression): raise TypeError("Expression must be string, got %s." % type_name(expression)) if not expression: raise ValueError("Expression cannot be empty.") exec(expression, namespace, variables) except: raise RuntimeError("Evaluating expression '%s' failed: %s" % (expression, "---"))
def _is_named(self, arg, variables=None): if not (is_string(arg) and '=' in arg): return False name, value = split_from_equals(arg) if value is None: return False if self._argspec.kwargs: return True if not self._argspec.supports_named: return False if variables: name = variables.replace_scalar(name) return name in self._argspec.positional
def _get_handler(self, name): handler = None if not name: raise DataError('Keyword name cannot be empty.') if not is_string(name): raise DataError('Keyword name must be a string.') if '.' in name: handler = self._get_explicit_handler(name) if not handler: handler = self._get_implicit_handler(name) if not handler: handler = self._get_bdd_style_handler(name) return handler
def _yield_visitors(self, visitors): # Avoid cyclic imports. Yuck. from robot.output import LOGGER importer = Importer('model modifier', logger=LOGGER) for visitor in visitors: try: if not is_string(visitor): yield visitor else: name, args = split_args_from_name_or_path(visitor) yield importer.import_class_or_module(name, args) except DataError as err: self._log_error(err.message)
def __init__(self, string, identifiers='$@%&*'): self.identifier = None self.base = None self.items = [] self.start = -1 self.end = -1 self._identifiers = identifiers self._may_have_internal_variables = False if not is_string(string): self._max_end = -1 return self._max_end = len(string) if self._split(string): self._finalize()
def convert_to_title_case(self, string, exclude=''): """Converts string to title case. Uses the following algorithm: - Split the string to words from whitespace characters (spaces, newlines, etc.). - Exclude words that are not all lower case. This preserves, for example, "OK" and "iPhone". - Exclude also words listed in the optional ``exclude`` argument. - Title case the first alphabetical character of each word that has not been excluded. - Join all words together so that original whitespace is preserved. Explicitly excluded words can be given as a list or as a string with words separated by a comma and an optional space. Examples: | ${str1} = | Convert To Title Case | hello, world! | | ${str2} = | Convert To Title Case | it's an OK iPhone | exclude=a, an, the | | Should Be Equal | ${str1} | Hello, World! | | Should Be Equal | ${str2} | It's an OK iPhone | The reason this keyword does not use Python's standard [https://docs.python.org/library/stdtypes.html#str.title|title()] method is that it can yield undesired results, for example, if strings contain upper case letters or special characters like apostrophes. It would, for example, convert "it's an OK iPhone" to "It'S An Ok Iphone". New in Robot Framework 3.2. """ if is_string(exclude): exclude = {e.strip() for e in exclude.split(',')} else: exclude = set(exclude) def title(word): if word in exclude or not word.islower(): return word for index, char in enumerate(word): if char.isalpha(): return word[:index] + word[index].title() + word[index + 1:] return word tokens = re.split(r'(\s+)', string, flags=re.UNICODE) return ''.join(title(token) for token in tokens)
def _import_if_needed(self, path_or_variables, args=None): if not is_string(path_or_variables): return path_or_variables LOGGER.info("Importing variable file '%s' with args %s" % (path_or_variables, args)) if path_or_variables.lower().endswith('.yaml'): importer = YamlImporter() else: importer = PythonImporter() try: return importer.import_variables(path_or_variables, args) except: args = 'with arguments %s ' % seq2str2(args) if args else '' raise DataError("Processing variable file '%s' %sfailed: %s" % (path_or_variables, args, get_error_message()))