def format_string(self, template, *positional, **named): """Formats a ``template`` using the given ``positional`` and ``named`` arguments. The template can be either be a string or an absolute path to an existing file. In the latter case the file is read and its contents are used as the template. If the template file contains non-ASCII characters, it must be encoded using UTF-8. The template is formatted using Python's [https://docs.python.org/library/string.html#format-string-syntax|format string syntax]. Placeholders are marked using ``{}`` with possible field name and format specification inside. Literal curly braces can be inserted by doubling them like `{{` and `}}`. Examples: | ${to} = | Format String | To: {} <{}> | ${user} | ${email} | | ${to} = | Format String | To: {name} <{email}> | name=${name} | email=${email} | | ${to} = | Format String | To: {user.name} <{user.email}> | user=${user} | | ${xx} = | Format String | {:*^30} | centered | | ${yy} = | Format String | {0:{width}{base}} | ${42} | base=X | width=10 | | ${zz} = | Format String | ${CURDIR}/template.txt | positional | named=value | New in Robot Framework 3.1. """ if os.path.isabs(template) and os.path.isfile(template): template = template.replace('/', os.sep) logger.info('Reading template from file <a href="%s">%s</a>.' % (template, template), html=True) with Utf8Reader(template) as reader: template = reader.read() return template.format(*positional, **named)
def _read(self, path): try: # IronPython handles BOM incorrectly if not using binary mode: # https://ironpython.codeplex.com/workitem/34655 with open(path, 'rb') as data: if os.path.splitext(path)[1].lower() in ('.rest', '.rst'): return read_rest(data) return Utf8Reader(data).read() except: raise DataError(get_error_message())
def read(self, tsvfile, populator): process = False for row in Utf8Reader(tsvfile).readlines(): row = self._process_row(row) cells = [self._process_cell(cell) for cell in self.split_row(row)] if cells and cells[0].strip().startswith('*') and \ populator.start_table([c.replace('*', '') for c in cells]): process = True elif process: populator.add(cells) populator.eof()
def read(self, file, populator, path=None): path = path or getattr(file, 'name', '<file-like object>') process = False for lineno, line in enumerate(Utf8Reader(file).readlines(), start=1): cells = self.split_row(line.rstrip()) cells = list(self._check_deprecations(cells, path, lineno)) if cells and cells[0].strip().startswith('*') and \ populator.start_table([c.replace('*', '').strip() for c in cells]): process = True elif process: populator.add(cells) return populator.eof()
def read(self, file, populator, path=None): path = path or getattr(file, 'name', '<file-like object>') process = False for row in Utf8Reader(file).readlines(): row = self._process_row(row) cells = [ self._process_cell(cell, path) for cell in self.split_row(row) ] self._deprecate_empty_data_cells_in_tsv_format(cells, path) if cells and cells[0].strip().startswith('*') and \ populator.start_table([c.replace('*', '') for c in cells]): process = True elif process: populator.add(cells) return populator.eof()
def _load(self, path): ''' The general idea is to do a quick parse, creating a list of tables. Each table is nothing more than a list of rows, with each row being a list of cells. Additional parsing such as combining rows into statements is done on demand. This first pass is solely to read in the plain text and organize it by table. ''' self.tables = [] current_table = DefaultTable(self) with Utf8Reader(path) as f: # N.B. the caller should be catching errors self.raw_text = f.read() f._file.seek(0) # bleh; wish this wasn't a private property matcher = Matcher(re.IGNORECASE) for linenumber, raw_text in enumerate(f.readlines()): linenumber += 1 # start counting at 1 rather than zero # this mimics what the robot TSV reader does -- # it replaces non-breaking spaces with regular spaces, # and then strips trailing whitespace raw_text = raw_text.replace(u'\xA0', ' ') raw_text = raw_text.rstrip() # FIXME: I'm keeping line numbers but throwing away # where each cell starts. I should be preserving that # (though to be fair, robot is throwing that away so # I'll have to write my own splitter if I want to save # the character position) cells = TxtReader.split_row(raw_text) _heading_regex = r'^\s*\*+\s*(.*?)[ *]*$' if matcher(_heading_regex, cells[0]): # we've found the start of a new table table_name = matcher.group(1) current_table = tableFactory(self, linenumber, table_name, raw_text) self.tables.append(current_table) else: current_table.append(Row(linenumber, raw_text, cells))
def format_string(self, template, *positional, **named): """Formats a ``template`` using the given ``positional`` and ``named`` arguments. If the given ``template`` is a valid absolute file path, opens the file in read mode and then format its content using the given ``positional`` and ``named`` arguments. The file is read as it is, that means, any trailing newlines, spaces and etc would not be ignored. This keyword uses python's string format. For more information see: [https://docs.python.org/library/string.html#formatstrings]|Format syntax] Examples: `Considering the file C:\\template.txt contents as "My {test} String"` | ${result} = | Format String | C:\\template.txt | | test=awesome | | Should Be Equal | ${result} | My awesome String | | ${result} = | Format String | User {} is not a admin user. | non-admin | | | Should Be Equal | ${result} | User non-admin is not a admin user. | | ${result} = | Format String | Username: {username} - Password: {password} | | username=Robot | password=Framework | | Should Be Equal | ${result} | Username: Robot - Password: Framework | | ${result} = | Format String | Document {} is missing on folder {folder} | tests.robot | folder=/home | | Should Be Equal | ${result} | Document tests.robot is missing on folder /home | | ${result} = | Format String | Uploaded file: {} should not be bigger than {}. | photo.jpg | 5MB | | Should Be Equal | ${result} | Uploaded file: photo.jpg should not be bigger than 5MB. | New in Robot Framework 3.1. """ if os.path.isabs(template) and os.path.isfile(template): template = template.replace("/", os.sep) logger.info('Reading template from file <a href="%s">%s</a>' % (template, template), html=True) with Utf8Reader(template) as reader: template = reader.read() else: template = template return template.format(*positional, **named)
def test_invalid_encoding(self): self._create(STRING.splitlines()[-1], 'ISO-8859-5') with Utf8Reader(PATH) as reader: assert_raises(UnicodeDecodeError, reader.read)
def test_readlines(self): with Utf8Reader(PATH) as reader: assert_equals(list(reader.readlines()), STRING.splitlines(True))
def test_stringio_is_ok(self): f = StringIO(self.BOM + STRING.encode('UTF-8')) with Utf8Reader(f) as reader: assert_equals(reader.read(), STRING) assert_equals(f.closed, False)
def test_read_open_file(self): with open(PATH, 'rb') as f: with Utf8Reader(f) as reader: assert_equals(reader.read(), STRING) assert_equals(f.closed, False)
def test_read(self): with Utf8Reader(PATH) as reader: f = reader._file assert_equals(reader.read(), STRING) assert_equals(f.closed, True)