6 new revisions:
Revision: 6845cf31f5ce
Author: Pekka Klärck
Date: Wed Dec 14 13:19:53 2011
Log: no need for trailing commas
http://code.google.com/p/robotframework/source/detail?r=6845cf31f5ce
Revision: 03b05dc01ff5
Author: Pekka Klärck
Date: Sat Dec 17 13:11:32 2011
Log: Small JSON dumping cleanup. Mainly use leading underscore only
with ab...
http://code.google.com/p/robotframework/source/detail?r=03b05dc01ff5
Revision: 9602da4de727
Author: Pekka Klärck
Date: Sat Dec 17 13:11:44 2011
Log: Automated merge with https://code.google.com/p/robotframework/
http://code.google.com/p/robotframework/source/detail?r=9602da4de727
Revision: db331d5484b5
Author: Pekka Klärck
Date: Sun Dec 18 02:58:17 2011
Log: Separate LogWriter and ReportWriter classes similarly as
OutputWriter ...
http://code.google.com/p/robotframework/source/detail?r=db331d5484b5
Revision: 3db91297c64a
Author: Pekka Klärck
Date: Sun Dec 18 03:01:57 2011
Log: small test cleanup
http://code.google.com/p/robotframework/source/detail?r=3db91297c64a
Revision: fff854557ae3
Author: Pekka Klärck
Date: Sun Dec 18 03:09:57 2011
Log: StringCache: resuse also zero index instance
http://code.google.com/p/robotframework/source/detail?r=fff854557ae3
==============================================================================
Revision: 6845cf31f5ce
Author: Pekka Klärck
Date: Wed Dec 14 13:19:53 2011
Log: no need for trailing commas
http://code.google.com/p/robotframework/source/detail?r=6845cf31f5ce
Modified:
/src/robot/reporting/jswriter.py
=======================================
--- /src/robot/reporting/jswriter.py Tue Dec 13 06:59:35 2011
+++ /src/robot/reporting/jswriter.py Wed Dec 14 13:19:53 2011
@@ -54,7 +54,7 @@
postfix = ');' + os.linesep
threshold = self.split_threshold
for index in xrange(0, len(strings), threshold):
- self._write_json(prefix, strings[index:index+threshold],
postfix),
+ self._write_json(prefix, strings[index:index+threshold],
postfix)
def _write_data(self, data):
for key in data:
==============================================================================
Revision: 03b05dc01ff5
Author: Pekka Klärck
Date: Sat Dec 17 13:11:32 2011
Log: Small JSON dumping cleanup. Mainly use leading underscore only
with abstract classes, not classes used only within a module where they are
created.
http://code.google.com/p/robotframework/source/detail?r=03b05dc01ff5
Modified:
/src/robot/reporting/jsonwriter.py
=======================================
--- /src/robot/reporting/jsonwriter.py Tue Dec 13 05:41:18 2011
+++ /src/robot/reporting/jsonwriter.py Sat Dec 17 13:11:32 2011
@@ -14,6 +14,7 @@
import os
+
class JsonWriter(object):
def __init__(self, output, separator=''):
@@ -40,13 +41,13 @@
def __init__(self, output):
self._output = output
- self._dumpers = (_MappingDumper(self),
- _IntegerDumper(self),
- _TupleListDumper(self),
- _RawStringDumper(self),
- _Base64StringDumper(self),
- _NoneDumper(self),
- _DictDumper(self))
+ self._dumpers = (MappingDumper(self),
+ IntegerDumper(self),
+ TupleListDumper(self),
+ RawStringDumper(self),
+ Base64StringDumper(self),
+ NoneDumper(self),
+ DictDumper(self))
def dump(self, data, mapping=None):
for dumper in self._dumpers:
@@ -59,7 +60,7 @@
self._output.write(data)
-class _DataDumper(object):
+class _Dumper(object):
_handled_types = None
def __init__(self, jsondumper):
@@ -73,7 +74,7 @@
raise NotImplementedError
-class _RawStringDumper(_DataDumper):
+class RawStringDumper(_Dumper):
_replace =
{'\\': '\\\\', '"': '\\"', '\t': '\\t', '\n': '\\n', '\r': '\\r'}
def handles(self, data, mapping):
@@ -93,21 +94,21 @@
yield char if 31 < val < 127 else '\\u%04x' % val
-class _Base64StringDumper(_DataDumper):
+class Base64StringDumper(_Dumper):
_handled_types = basestring
def dump(self, data, mapping):
self._write('"%s"' % data)
-class _IntegerDumper(_DataDumper):
+class IntegerDumper(_Dumper):
_handled_types = (int, long)
def dump(self, data, mapping):
self._write(str(data))
-class _DictDumper(_DataDumper):
+class DictDumper(_Dumper):
_handled_types = dict
def dump(self, data, mapping):
@@ -122,7 +123,7 @@
self._write('}')
-class _TupleListDumper(_DataDumper):
+class TupleListDumper(_Dumper):
_handled_types = (tuple, list)
def dump(self, data, mapping):
@@ -135,7 +136,7 @@
self._write(']')
-class _MappingDumper(_DataDumper):
+class MappingDumper(_Dumper):
def handles(self, data, mapping):
try:
@@ -147,7 +148,7 @@
self._write(mapping[data])
-class _NoneDumper(_DataDumper):
+class NoneDumper(_Dumper):
def handles(self, data, mapping):
return data is None
==============================================================================
Revision: 9602da4de727
Author: Pekka Klärck
Date: Sat Dec 17 13:11:44 2011
Log: Automated merge with https://code.google.com/p/robotframework/
http://code.google.com/p/robotframework/source/detail?r=9602da4de727
==============================================================================
Revision: db331d5484b5
Author: Pekka Klärck
Date: Sun Dec 18 02:58:17 2011
Log: Separate LogWriter and ReportWriter classes similarly as
OutputWriter and XUnitWriter. This makes builders module redundant.
http://code.google.com/p/robotframework/source/detail?r=db331d5484b5
Added:
/src/robot/reporting/logreportwriters.py
/utest/reporting/test_logreportwriters.py
Deleted:
/utest/reporting/test_builders.py
Modified:
/src/robot/reporting/builders.py
=======================================
--- /dev/null
+++ /src/robot/reporting/logreportwriters.py Sun Dec 18 02:58:17 2011
@@ -0,0 +1,58 @@
+# Copyright 2008-2011 Nokia Siemens Networks Oyj
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# 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 __future__ import with_statement
+import os
+import os.path
+import codecs
+
+from .jswriter import SplitLogWriter
+from .htmlfilewriter import HtmlFileWriter
+
+
+class _LogReportWriter(object):
+
+ def __init__(self, js_model):
+ self._js_model = js_model
+
+ def _write_file(self, path, config, template):
+ outfile = codecs.open(path, 'wb', encoding='UTF-8') \
+ if isinstance(path, basestring) else path # unit test hook
+ with outfile:
+ writer = HtmlFileWriter(outfile, self._js_model, config)
+ writer.write(template)
+
+
+class LogWriter(_LogReportWriter):
+
+ def write(self, path, config):
+ self._write_file(path, config, 'log.html')
+ if self._js_model.split_results:
+ self._write_split_logs(os.path.splitext(path)[0])
+
+ def _write_split_logs(self, base):
+ for index, (keywords, strings) in
enumerate(self._js_model.split_results):
+ index += 1 # enumerate accepts start index only in Py 2.6+
+ self._write_split_log(index, keywords, strings, '%s-%d.js' %
(base, index))
+
+ def _write_split_log(self, index, keywords, strings, path):
+ with codecs.open(path, 'wb', encoding='UTF-8') as outfile:
+ writer = SplitLogWriter(outfile)
+ writer.write(keywords, strings, index, os.path.basename(path))
+
+
+class ReportWriter(_LogReportWriter):
+
+ def write(self, path, config):
+ self._write_file(path, config, 'report.html')
=======================================
--- /dev/null
+++ /utest/reporting/test_logreportwriters.py Sun Dec 18 02:58:17 2011
@@ -0,0 +1,39 @@
+import unittest
+
+from robot.reporting.logreportwriters import LogWriter
+from robot.utils.asserts import assert_true, assert_equals
+
+
+class LogWriterWithMockedWriting(LogWriter):
+
+ def __init__(self, model):
+ LogWriter.__init__(self, model)
+ self.split_write_calls = []
+ self.write_called = False
+
+ def _write_split_log(self, index, keywords, strings, path):
+ self.split_write_calls.append((index, keywords, strings, path))
+
+ def _write_file(self, output, config, template):
+ self.write_called = True
+
+
+
+class TestLogWriter(unittest.TestCase):
+
+ def test_splitting_log(self):
+ class model:
+ split_results = [((0, 1, 2, -1), ('*', '*1', '*2')),
+ ((0, 1, 0, 42), ('*','*x')),
+ (((1, 2), (3, 4, ())), ('*',))]
+ writer = LogWriterWithMockedWriting(model)
+ writer.write('mylog.html', None)
+ assert_true(writer.write_called)
+ assert_equals([(1, (0, 1, 2, -1), ('*', '*1', '*2'), 'mylog-1.js'),
+ (2, (0, 1, 0, 42), ('*', '*x'), 'mylog-2.js'),
+ (3, ((1, 2), (3, 4, ())), ('*',), 'mylog-3.js')],
+ writer.split_write_calls)
+
+
+if __name__ == '__main__':
+ unittest.main()
=======================================
--- /utest/reporting/test_builders.py Sun Dec 4 23:44:52 2011
+++ /dev/null
@@ -1,37 +0,0 @@
-from StringIO import StringIO
-import unittest
-from robot.reporting.builders import LogBuilder
-from robot.utils.asserts import assert_true, assert_equals
-
-
-class _LogBuilderWithMockedWriting(LogBuilder):
-
- def __init__(self, model):
- LogBuilder.__init__(self, model)
- self._split_write_calls = []
- self._write_called = False
-
- def _write_split_log(self, index, keywords, strings, path):
- self._split_write_calls.append((index, keywords, strings, path))
-
- def _write_file(self, output, config, template):
- self._write_called = True
-
-
-class TestLogBuilder(unittest.TestCase):
-
- def test_splitting_log(self):
- model = lambda:0
- splitted_result1 = [[1],['*']]
- splitted_result2 = [[4],['A']]
- model.split_results = [splitted_result1, splitted_result2]
- log_builder = _LogBuilderWithMockedWriting(model)
- log_builder.build(object(), object())
- assert_true(log_builder._write_called)
- assert_equals([(1, [1], ['*'], '-1.js'),
- (2, [4], ['A'], '-2.js')],
- log_builder._split_write_calls)
-
-
-if __name__ == '__main__':
- unittest.main()
=======================================
--- /src/robot/reporting/builders.py Wed Dec 14 02:20:42 2011
+++ /src/robot/reporting/builders.py Sun Dec 18 02:58:17 2011
@@ -13,17 +13,14 @@
# limitations under the License.
from __future__ import with_statement
-import os
-import os.path
-import codecs
+
from robot.errors import DataError
from robot.output import LOGGER
from robot.result.outputwriter import OutputWriter
-from .jswriter import SplitLogWriter
from .xunitwriter import XUnitWriter
-from .htmlfilewriter import HtmlFileWriter
+from .logreportwriters import LogWriter, ReportWriter
class OutputBuilder(object):
@@ -57,49 +54,32 @@
LOGGER.output_file('XUnit', path)
-class _HTMLFileBuilder(object):
+
+class LogBuilder(object):
def __init__(self, js_model):
self._js_model = js_model
- def _write_file(self, output, config, template):
- outfile = codecs.open(output, 'wb', encoding='UTF-8') \
- if isinstance(output, basestring) else output # isinstance is
unit test hook
- with outfile:
- writer = HtmlFileWriter(outfile, self._js_model, config)
- writer.write(template)
-
-
-class LogBuilder(_HTMLFileBuilder):
-
- def build(self, output, config):
+ def build(self, path, config):
try:
- self._write_file(output, config, 'log.html')
- self._write_split_logs_if_needed(output)
+ LogWriter(self._js_model).write(path, config)
except EnvironmentError, err:
# Cannot use err.filename due to
http://bugs.jython.org/issue1825
# and thus error has wrong file name if writing split log
fails.
- LOGGER.error("Writing log file '%s' failed: %s" % (output,
err.strerror))
+ LOGGER.error("Writing log file '%s' failed: %s" % (path,
err.strerror))
else:
- LOGGER.output_file('Log', output)
-
- def _write_split_logs_if_needed(self, output):
- base = os.path.splitext(output)[0] if isinstance(output,
basestring) else ''
- for index, (keywords, strings) in
enumerate(self._js_model.split_results):
- index += 1 # enumerate accepts start index only in Py 2.6+
- self._write_split_log(index, keywords, strings, '%s-%d.js' %
(base, index))
-
- def _write_split_log(self, index, keywords, strings, path):
- with codecs.open(path, 'wb', encoding='UTF-8') as outfile:
- writer = SplitLogWriter(outfile)
- writer.write(keywords, strings, index, os.path.basename(path))
-
-
-class ReportBuilder(_HTMLFileBuilder):
+ LOGGER.output_file('Log', path)
+
+
+
+class ReportBuilder(object):
+
+ def __init__(self, js_model):
+ self._js_model = js_model
def build(self, path, config):
try:
- self._write_file(path, config, 'report.html')
+ ReportWriter(self._js_model).write(path, config)
except EnvironmentError, err:
LOGGER.error("Writing report file '%s' failed: %s" % (path,
err.strerror))
else:
==============================================================================
Revision: 3db91297c64a
Author: Pekka Klärck
Date: Sun Dec 18 03:01:57 2011
Log: small test cleanup
http://code.google.com/p/robotframework/source/detail?r=3db91297c64a
Modified:
/utest/reporting/test_stringcache.py
=======================================
--- /utest/reporting/test_stringcache.py Wed Dec 14 04:26:09 2011
+++ /utest/reporting/test_stringcache.py Sun Dec 18 03:01:57 2011
@@ -14,14 +14,14 @@
# To make test reproducable log the random seed if test fails
self._seed = long(time.time() * 256)
random.seed(self._seed)
- self._text_cache = StringCache()
+ self.cache = StringCache()
def _verify_text(self, string, expected):
- self._text_cache.add(string)
- assert_equals(('*', expected), self._text_cache.dump())
+ self.cache.add(string)
+ assert_equals(('*', expected), self.cache.dump())
def _compress(self, text):
- return self._text_cache._encode(text)
+ return self.cache._encode(text)
def test_short_test_is_not_compressed(self):
self._verify_text('short', '*short')
@@ -32,16 +32,16 @@
def test_coded_string_is_at_most_1_characters_longer_than_raw(self):
for i in range(300):
- id = self._text_cache.add(self._generate_random_string(i))
- assert_true(i+1 >= len(self._text_cache.dump()[id]),
- msg='len(self._text_cache.dump()[id]) (%s) > i+1
(%s) [test seed = %s]' % \
- (len(self._text_cache.dump()[id]), i+1,
self._seed))
+ id = self.cache.add(self._generate_random_string(i))
+ assert_true(i+1 >= len(self.cache.dump()[id]),
+ 'len(self._text_cache.dump()[id]) (%s) > i+1 (%s)
[test seed = %s]'
+ % (len(self.cache.dump()[id]), i+1, self._seed))
def test_long_random_strings_are_compressed(self):
for i in range(30):
value = self._generate_random_string(300)
- id = self._text_cache.add(value)
- assert_equals(self._compress(value),
self._text_cache.dump()[id],\
+ id = self.cache.add(value)
+ assert_equals(self._compress(value), self.cache.dump()[id],
msg='Did not compress [test seed = %s]' %
self._seed)
def _generate_random_string(self, length):
==============================================================================
Revision: fff854557ae3
Author: Pekka Klärck
Date: Sun Dec 18 03:09:57 2011
Log: StringCache: resuse also zero index instance
http://code.google.com/p/robotframework/source/detail?r=fff854557ae3
Modified:
/src/robot/reporting/stringcache.py
/utest/reporting/test_stringcache.py
=======================================
--- /src/robot/reporting/stringcache.py Wed Dec 14 04:26:09 2011
+++ /src/robot/reporting/stringcache.py Sun Dec 18 03:09:57 2011
@@ -30,14 +30,15 @@
class StringCache(object):
_compress_threshold = 80
_use_compressed_threshold = 1.1
+ _zero_index = StringIndex(0)
def __init__(self):
- self._cache = {'*': StringIndex(0)}
+ self._cache = {'*': self._zero_index}
self._index = 1
def add(self, text):
if not text:
- return StringIndex(0)
+ return self._zero_index
text = self._encode(text)
if text not in self._cache:
self._cache[text] = StringIndex(self._index)
=======================================
--- /utest/reporting/test_stringcache.py Sun Dec 18 03:01:57 2011
+++ /utest/reporting/test_stringcache.py Sun Dec 18 03:09:57 2011
@@ -47,6 +47,13 @@
def _generate_random_string(self, length):
return ''.join(random.choice(string.digits) for _ in range(length))
+ def test_indices_reused_instances(self):
+ strings = ['', 'short', 'long'*1000, '']
+ indices1 = [self.cache.add(s) for s in strings]
+ indices2 = [self.cache.add(s) for s in strings]
+ for i1, i2 in zip(indices1, indices2):
+ assert_true(i1 is i2, 'not same: %s and %s' % (i1, i2))
+
class TestStringIndex(unittest.TestCase):