2 new revisions:
Revision: 6b6bc12b552e
Author: Robot Framework Developers <[email protected]>
Date: Tue Jan 24 20:55:20 2012
Log: datafilewriter: cleanup based on code review...
http://code.google.com/p/robotframework/source/detail?r=6b6bc12b552e
Revision: 4e31ecbd8594
Author: Robot Framework Developers <[email protected]>
Date: Tue Jan 24 20:55:42 2012
Log: filewriters: cleanup
http://code.google.com/p/robotframework/source/detail?r=4e31ecbd8594
==============================================================================
Revision: 6b6bc12b552e
Author: Robot Framework Developers <[email protected]>
Date: Tue Jan 24 20:55:20 2012
Log: datafilewriter: cleanup based on code review
1) Rename WriteConfiguraition -> WritingContext
2) Remove unnecessary path argument from WritingContext
3) Make WritingContext a context manager
4) Validate given format, raise DataError if not valid
5) Added valid formats as attributes to WritingContext
http://code.google.com/p/robotframework/source/detail?r=6b6bc12b552e
Modified:
/src/robot/parsing/model.py
/src/robot/writer/datafilewriter.py
/utest/writer/test_write_configuration.py
=======================================
--- /src/robot/parsing/model.py Wed Jan 18 22:55:12 2012
+++ /src/robot/parsing/model.py Tue Jan 24 20:55:20 2012
@@ -102,7 +102,7 @@
See
also :py:meth:`robot.writer.datafilewriter.DataFileWriter.write`
"""
- return DataFileWriter().write(self, **options)
+ return DataFileWriter(**options).write(self)
class TestCaseFile(_TestData):
=======================================
--- /src/robot/writer/datafilewriter.py Fri Jan 20 03:06:10 2012
+++ /src/robot/writer/datafilewriter.py Tue Jan 24 20:55:20 2012
@@ -12,43 +12,44 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import with_statement
import os
+from robot.errors import DataError
from .filewriters import FileWriter
class DataFileWriter(object):
- """The DataFileWriter object. It is used to write parsed Robot
Framework
- test data file objects back to disk.
- """
-
- def write(self, datafile, **options):
+ """Writes parsed Robot Framework test data file objects back to
disk."""
+
+ def __init__(self, **options):
+ """:param options: used to create
a :py:class:`.WriteConfiguration`."""
+ self._options = options
+
+ def write(self, datafile):
"""Writes given `datafile` using `**options`.
:param datafile: A robot.parsing.model.DataFile object to be
written
- :param options: A :py:class:`.WriteConfiguration` is created with
these
"""
- configuration = WriteConfiguration(datafile, **options)
- FileWriter(configuration).write(datafile)
- configuration.finish()
+ with WritingContext(datafile, **self._options) as ctx:
+ FileWriter(ctx).write(datafile)
-class WriteConfiguration(object):
- """The WriteConfiguration object. It contains configuration used in
- writing a test data file to disk.
- """
-
- def __init__(self, datafile, path=None, format=None, output=None,
- recursive=False, pipe_separated=False,
- line_separator=os.linesep):
+class WritingContext(object):
+ """Contains configuration used in writing a test data file to disk."""
+ encoding = 'UTF-8'
+ txt_format = 'txt'
+ html_format = 'html'
+ tsv_format = 'tsv'
+ _formats = [txt_format, html_format, tsv_format]
+
+ def __init__(self, datafile, format='', output=None,
+ pipe_separated=False, line_separator=os.linesep):
"""
:param datafile: The datafile to be written.
:type datafile: :py:class:`~robot.parsing.model.TestCaseFile`,
:py:class:`~robot.parsing.model.ResourceFile`,
:py:class:`~robot.parsing.model.TestDataDirectory`
- :param str path: Output file name. If omitted, basename of the
`source`
- attribute of the given `datafile` is used. If `path` contains
- extension, it overrides the value of `format` option.
:param str format: Output file format. If omitted, read from the
extension of the `source` attribute of the given `datafile`.
:param output: An open, file-like object used in writing. If
@@ -57,46 +58,50 @@
:param bool pipe_separated: Whether to use pipes as separator when
output file format is txt.
:param str line_separator: Line separator used in output files.
+
+ If `output` is not given, an output file is created based on the
source
+ of the given datafile and value of `format`. Examples:
+
+ WriteConfiguration(datafile, output=StringIO) ->
+ Output written in the StringIO instance using format of
+ `datafile.source`
+ WriteConfiguration(datafile, format='html') ->
+ Output file is created from `datafile.source` by stripping
+ extension and replacing it with `html`.
"""
self.datafile = datafile
- self.recursive = recursive
self.pipe_separated = pipe_separated
self.line_separator = line_separator
self._given_output = output
- self._path = path
- self._format = format
- self._output = output
-
- @property
- def output(self):
- if not self._output:
- self._output = open(self._get_source(), 'wb')
- return self._output
-
- @property
- def format(self):
- return self._format_from_path() or self._format or
self._format_from_file()
-
- def finish(self):
+ self.format = self._validate_format(format) or
self._format_from_file()
+ self.output = output
+
+ def __enter__(self):
+ if not self.output:
+ self.output = open(self._output_path(), 'wb')
+ return self
+
+ def __exit__(self, *exc_info):
if self._given_output is None:
- self._output.close()
-
- def _get_source(self):
- return self._path or '%s.%s' % (self._basename(), self.format)
-
- def _basename(self):
- return os.path.splitext(self._source_from_file())[0]
-
- def _source_from_file(self):
- return getattr(self.datafile, 'initfile', self.datafile.source)
-
- def _format_from_path(self):
- if not self._path:
- return ''
- return self._format_from_extension(self._path)
+ self.output.close()
+
+ def _validate_format(self, format):
+ format = format.lower()
+ if format and format not in self._formats:
+ raise DataError('Invalid format: %s' % format)
+ return format
def _format_from_file(self):
return self._format_from_extension(self._source_from_file())
def _format_from_extension(self, path):
return os.path.splitext(path)[1][1:].lower()
+
+ def _output_path(self):
+ return '%s.%s' % (self._base_name(), self.format)
+
+ def _base_name(self):
+ return os.path.splitext(self._source_from_file())[0]
+
+ def _source_from_file(self):
+ return getattr(self.datafile, 'initfile', self.datafile.source)
=======================================
--- /utest/writer/test_write_configuration.py Wed Jan 18 22:55:12 2012
+++ /utest/writer/test_write_configuration.py Tue Jan 24 20:55:20 2012
@@ -1,28 +1,26 @@
import unittest
import os
-from robot.writer.datafilewriter import WriteConfiguration
+from robot import DataError
+from robot.writer.datafilewriter import WritingContext
from robot.parsing.model import TestCaseFile
-from robot.utils.asserts import assert_equals
+from robot.utils.asserts import assert_equals, assert_raises
HTML_SOURCE = os.path.abspath('foo.html')
TXT_SOURCE= os.path.abspath('foo.txt')
-class TestOutput(unittest.TestCase):
+class TestOutputFile(unittest.TestCase):
def test_source_file_is_used_by_default(self):
- self._assert_source(HTML_SOURCE, source=HTML_SOURCE)
-
- def test_given_path_override_source(self):
- self._assert_source(TXT_SOURCE, source=HTML_SOURCE,
path=TXT_SOURCE)
+ self._assert_output_file(HTML_SOURCE, source=HTML_SOURCE)
def test_given_format_overrides_source_extension(self):
- self._assert_source(TXT_SOURCE, HTML_SOURCE, format='txt')
-
- def _assert_source(self, expected, source=None, path=None,
format=None):
- ctx = WriteConfiguration(TestCaseFile(source=source), path=path,
format=format)
- assert_equals(ctx._get_source(), expected)
+ self._assert_output_file(TXT_SOURCE, HTML_SOURCE, format='txt')
+
+ def _assert_output_file(self, expected, source=None, format=''):
+ ctx = WritingContext(TestCaseFile(source=source), format=format)
+ assert_equals(ctx._output_path() , expected)
class TestFormat(unittest.TestCase):
@@ -30,13 +28,13 @@
def test_format_from_source_file_is_used_by_default(self):
self._assert_format('html', source=HTML_SOURCE)
- def test_extension_in_path_override_format(self):
- self._assert_format('txt', format='html', path=TXT_SOURCE)
-
- def test_extension_in_given_path_override_extension_in_source(self):
- self._assert_format('txt', source=HTML_SOURCE, path=TXT_SOURCE)
-
- def _assert_format(self, expected, source=None, format=None,
path=None):
+ def test_explicit_format_overrides_default(self):
+ self._assert_format('txt', source=HTML_SOURCE, format='txt')
+
+ def test_creating_with_invalid_format_fails(self):
+ assert_raises(DataError, WritingContext, datafile=None,
format='inv')
+
+ def _assert_format(self, expected, source, format=''):
data = TestCaseFile(source=source)
- ctx = WriteConfiguration(data, format=format, path=path)
+ ctx = WritingContext(data, format=format)
assert_equals(ctx.format, expected)
==============================================================================
Revision: 4e31ecbd8594
Author: Robot Framework Developers <[email protected]>
Date: Tue Jan 24 20:55:42 2012
Log: filewriters: cleanup
http://code.google.com/p/robotframework/source/detail?r=4e31ecbd8594
Modified:
/src/robot/writer/filewriters.py
=======================================
--- /src/robot/writer/filewriters.py Fri Jan 20 04:29:42 2012
+++ /src/robot/writer/filewriters.py Tue Jan 24 20:55:42 2012
@@ -11,7 +11,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-from robot.writer.htmlformatter import HtmlFormatter
try:
import csv
@@ -22,35 +21,34 @@
from robot import utils
from .formatters import TsvFormatter, TxtFormatter, PipeFormatter
+from .htmlformatter import HtmlFormatter
from .htmltemplate import TEMPLATE_START, TEMPLATE_END
-def FileWriter(configuration):
+def FileWriter(context):
"""Creates and returns a FileWriter object.
- :param configuration: Type of returned FileWriter is determined based
on
- `configuration.format`. `configuration` is also passed to created
- writer.
- :type configuration: :py:class:`WriteConfiguration`
+ :param context: Type of returned FileWriter is determined based on
+ `context.format`. `context` is also passed to created writer.
+ :type context: :py:class:`WritingContext`
"""
- writer_class = {'tsv': TsvFileWriter,
- 'txt': TxtFileWriter,
- 'html': HtmlFileWriter}[configuration.format]
- return writer_class(configuration)
-
-
-def TxtFileWriter(configuration):
- writer_class = PipeSeparatedTxtWriter if configuration.pipe_separated \
- else SpaceSeparatedTxtWriter
- return writer_class(configuration)
+ if context.format == context.html_format:
+ return HtmlFileWriter(context)
+ if context.format == context.tsv_format:
+ return TsvFileWriter(context)
+ if context.pipe_separated:
+ return PipeSeparatedTxtWriter(context)
+ return SpaceSeparatedTxtWriter(context)
class _DataFileWriter(object):
_formatter = None
+ _write_row = NotImplemented
def __init__(self, configuration):
self._output = configuration.output
self._line_separator = configuration.line_separator
+ self._encoding = configuration.encoding
def write(self, datafile):
for table in datafile:
@@ -80,7 +78,7 @@
self._write_row(row)
def _encode(self, row):
- return row.encode('UTF-8')
+ return row.encode(self._encoding)
class SpaceSeparatedTxtWriter(_DataFileWriter):
@@ -115,10 +113,7 @@
lineterminator=configuration.line_separator)
def _write_row(self, row):
- self._writer.writerow(self._encode(row))
-
- def _encode(self, row):
- return [c.encode('UTF-8') for c in row]
+ self._writer.writerow([self._encode(c) for c in row])
class HtmlFileWriter(_DataFileWriter):
@@ -129,7 +124,7 @@
self._name = configuration.datafile.name
self._writer = utils.HtmlWriter(configuration.output,
configuration.line_separator,
- encoding='UTF-8')
+ encoding=self._encoding)
def write(self, datafile):
self._writer.content(TEMPLATE_START % {'NAME': self._name},