Merge lp:~thomir-deactivatedaccount/autopilot/trunk-fix-plain-type-reprs into lp:autopilot
- trunk-fix-plain-type-reprs
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Thomi Richards |
Approved revision: | 449 |
Merged at revision: | 448 |
Proposed branch: | lp:~thomir-deactivatedaccount/autopilot/trunk-fix-plain-type-reprs |
Merge into: | lp:autopilot |
Diff against target: |
531 lines (+331/-61) 2 files modified
autopilot/introspection/types.py (+115/-60) autopilot/tests/unit/test_types.py (+216/-1) |
To merge this branch: | bzr merge lp:~thomir-deactivatedaccount/autopilot/trunk-fix-plain-type-reprs |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Christopher Lee (community) | Approve | ||
Review via email: mp+207699@code.launchpad.net |
This proposal supersedes a proposal from 2014-02-21.
Commit message
Make proxy object attributes look more pythonic when calling repr(...) or str(...) on them.
Description of the change
Fixes __repr__ and __str__ methods of the marshalled type classes so we hide the underlying dbus type, and make them look more pythonic in test output.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
- 444. By Thomi Richards
-
Merged trunk.
- 445. By Thomi Richards
-
Added missing test for Color unit tests.
- 446. By Thomi Richards
-
Fix flake8 issues.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:445
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Christopher Lee (veebers) wrote : | # |
Within the tests you mention UnicodeDecode but catch a UnicodeEncodeError, is this intentional?
278 + # in Python 2.x, str(u'\2603') *should* raise a UnicodeDecode error:
279 + except UnicodeEncodeError:
- 447. By Thomi Richards
-
Fix failing tests in Python 3.3.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:446
http://
Executed test runs:
SUCCESS: http://
deb: http://
FAILURE: http://
FAILURE: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 448. By Thomi Richards
-
Fix typo in comment.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:447
http://
Executed test runs:
SUCCESS: http://
deb: http://
FAILURE: http://
FAILURE: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:448
http://
Executed test runs:
SUCCESS: http://
deb: http://
FAILURE: http://
FAILURE: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:448
http://
Executed test runs:
SUCCESS: http://
deb: http://
FAILURE: http://
FAILURE: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 449. By Thomi Richards
-
Fix tests failing.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:449
http://
Executed test runs:
SUCCESS: http://
deb: http://
FAILURE: http://
FAILURE: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 450. By Thomi Richards
-
Fix failing test.
Preview Diff
1 | === modified file 'autopilot/introspection/types.py' |
2 | --- autopilot/introspection/types.py 2014-01-29 20:48:43 +0000 |
3 | +++ autopilot/introspection/types.py 2014-02-27 02:00:36 +0000 |
4 | @@ -46,7 +46,7 @@ |
5 | import six |
6 | |
7 | from autopilot.introspection.utilities import translate_state_keys |
8 | -from autopilot.utilities import sleep |
9 | +from autopilot.utilities import sleep, compatible_repr |
10 | |
11 | |
12 | logger = logging.getLogger(__name__) |
13 | @@ -217,68 +217,73 @@ |
14 | return _make_plain_type(value, parent=parent, name=name) |
15 | |
16 | |
17 | +def _get_repr_callable_for_value(value): |
18 | + repr_map = { |
19 | + dbus.Byte: _integer_repr, |
20 | + dbus.Int16: _integer_repr, |
21 | + dbus.Int32: _integer_repr, |
22 | + dbus.UInt16: _integer_repr, |
23 | + dbus.UInt32: _integer_repr, |
24 | + dbus.Int64: _integer_repr, |
25 | + dbus.UInt64: _integer_repr, |
26 | + dbus.String: _text_repr, |
27 | + dbus.ObjectPath: _text_repr, |
28 | + dbus.Signature: _text_repr, |
29 | + dbus.ByteArray: _bytes_repr, |
30 | + dbus.Boolean: _boolean_repr, |
31 | + dbus.Dictionary: _dict_repr, |
32 | + dbus.Double: _float_repr, |
33 | + dbus.Struct: _tuple_repr, |
34 | + dbus.Array: _list_repr, |
35 | + } |
36 | + if not six.PY3: |
37 | + repr_map[dbus.UTF8String] = _bytes_repr |
38 | + return repr_map.get(type(value), None) |
39 | + |
40 | + |
41 | +def _get_str_callable_for_value(value): |
42 | + str_map = { |
43 | + dbus.Boolean: _boolean_str, |
44 | + dbus.Byte: _integer_str, |
45 | + } |
46 | + return str_map.get(type(value), None) |
47 | + |
48 | + |
49 | +@compatible_repr |
50 | +def _integer_repr(self): |
51 | + return six.text_type(int(self)) |
52 | + |
53 | + |
54 | +def _create_generic_repr(target_type): |
55 | + return compatible_repr(lambda self: repr(target_type(self))) |
56 | + |
57 | +_bytes_repr = _create_generic_repr(six.binary_type) |
58 | +_text_repr = _create_generic_repr(six.text_type) |
59 | +_dict_repr = _create_generic_repr(dict) |
60 | +_list_repr = _create_generic_repr(list) |
61 | +_tuple_repr = _create_generic_repr(tuple) |
62 | +_float_repr = _create_generic_repr(float) |
63 | +_boolean_repr = _create_generic_repr(bool) |
64 | + |
65 | + |
66 | +def _create_generic_str(target_type): |
67 | + return compatible_repr(lambda self: str(target_type(self))) |
68 | + |
69 | + |
70 | +_boolean_str = _create_generic_str(bool) |
71 | +_integer_str = _integer_repr |
72 | + |
73 | + |
74 | def _make_plain_type(value, parent=None, name=None): |
75 | - def repr(self): |
76 | - # Convert our value to the pythonic type,and call __repr__ on it. |
77 | - # At the moment we switch based on our type, which is less than ideal. |
78 | - if six.PY3: |
79 | - long_type = int |
80 | - else: |
81 | - long_type = long |
82 | - dbus_integer_types = ( |
83 | - dbus.Byte, |
84 | - dbus.Int16, |
85 | - dbus.Int32, |
86 | - dbus.UInt16, |
87 | - dbus.UInt32, |
88 | - ) |
89 | - |
90 | - dbus_string_types = ( |
91 | - dbus.String, |
92 | - dbus.ObjectPath, |
93 | - dbus.Signature, |
94 | - ) |
95 | - |
96 | - # no UTFString in python 3. |
97 | - if six.PY3: |
98 | - dbus_binary_types = ( |
99 | - dbus.ByteArray, |
100 | - ) |
101 | - else: |
102 | - dbus_binary_types = ( |
103 | - dbus.ByteArray, |
104 | - dbus.UTF8String, |
105 | - ) |
106 | - |
107 | - if isinstance(self, dbus_integer_types): |
108 | - return int(self).__repr__() |
109 | - elif isinstance(self, (dbus.Int64, dbus.UInt64)): |
110 | - # Python 2 integer landling is... odd. The maximum integer size |
111 | - # changes depending on platform, so maybe we can get away with |
112 | - # using an int, in which case we should: |
113 | - if not six.PY3 and self <= six.MAXSIZE: |
114 | - return int(self).__repr__() |
115 | - return long_type(self).__repr__() |
116 | - elif isinstance(self, dbus_string_types): |
117 | - return six.text_type(self).__repr__() |
118 | - elif isinstance(self, dbus.Boolean): |
119 | - return bool(self).__repr__() |
120 | - elif isinstance(self, dbus_binary_types): |
121 | - return six.binary_type(self).__repr__() |
122 | - elif isinstance(self, dbus.Dictionary): |
123 | - return dict(self).__repr__() |
124 | - elif isinstance(self, dbus.Double): |
125 | - return float(self).__repr__() |
126 | - elif isinstance(self, dbus.Struct): |
127 | - return tuple(self).__repr__() |
128 | - elif isinstance(self, dbus.Array): |
129 | - return list(self).__repr__() |
130 | - else: |
131 | - return super(type(self), self).__repr__() |
132 | - |
133 | new_type_name = type(value).__name__ |
134 | new_type_bases = (type(value), PlainType) |
135 | - new_type_dict = dict(parent=parent, name=name, __repr__=repr) |
136 | + new_type_dict = dict(parent=parent, name=name) |
137 | + repr_callable = _get_repr_callable_for_value(value) |
138 | + if repr_callable: |
139 | + new_type_dict['__repr__'] = repr_callable |
140 | + str_callable = _get_str_callable_for_value(value) |
141 | + if str_callable: |
142 | + new_type_dict['__str__'] = str_callable |
143 | new_type = type(new_type_name, new_type_bases, new_type_dict) |
144 | return new_type(value) |
145 | |
146 | @@ -375,6 +380,11 @@ |
147 | def height(self): |
148 | return self[3] |
149 | |
150 | + @compatible_repr |
151 | + def __repr__(self): |
152 | + coords = u', '.join((str(c) for c in self)) |
153 | + return u'Rectangle(%s)' % (coords) |
154 | + |
155 | |
156 | class Point(_array_packed_type(2)): |
157 | |
158 | @@ -412,6 +422,10 @@ |
159 | def y(self): |
160 | return self[1] |
161 | |
162 | + @compatible_repr |
163 | + def __repr__(self): |
164 | + return u'Point(%d, %d)' % (self.x, self.y) |
165 | + |
166 | |
167 | class Size(_array_packed_type(2)): |
168 | |
169 | @@ -457,6 +471,10 @@ |
170 | def height(self): |
171 | return self[1] |
172 | |
173 | + @compatible_repr |
174 | + def __repr__(self): |
175 | + return u'Size(%d, %d)' % (self.w, self.h) |
176 | + |
177 | |
178 | class Color(_array_packed_type(4)): |
179 | |
180 | @@ -506,6 +524,15 @@ |
181 | def alpha(self): |
182 | return self[3] |
183 | |
184 | + @compatible_repr |
185 | + def __repr__(self): |
186 | + return u'Color(%d, %d, %d, %d)' % ( |
187 | + self.red, |
188 | + self.green, |
189 | + self.blue, |
190 | + self.alpha |
191 | + ) |
192 | + |
193 | |
194 | class DateTime(_array_packed_type(1)): |
195 | |
196 | @@ -603,6 +630,17 @@ |
197 | return other == self._cached_dt |
198 | return super(DateTime, self).__eq__(other) |
199 | |
200 | + @compatible_repr |
201 | + def __repr__(self): |
202 | + return u'DateTime(%d-%02d-%02d %02d:%02d:%02d)' % ( |
203 | + self.year, |
204 | + self.month, |
205 | + self.day, |
206 | + self.hour, |
207 | + self.minute, |
208 | + self.second |
209 | + ) |
210 | + |
211 | |
212 | class Time(_array_packed_type(4)): |
213 | |
214 | @@ -683,6 +721,15 @@ |
215 | return other == self._cached_time |
216 | return super(Time, self).__eq__(other) |
217 | |
218 | + @compatible_repr |
219 | + def __repr__(self): |
220 | + return u'Time(%02d:%02d:%02d.%03d)' % ( |
221 | + self.hour, |
222 | + self.minute, |
223 | + self.second, |
224 | + self.millisecond |
225 | + ) |
226 | + |
227 | |
228 | class Point3D(_array_packed_type(3)): |
229 | |
230 | @@ -725,3 +772,11 @@ |
231 | @property |
232 | def z(self): |
233 | return self[2] |
234 | + |
235 | + @compatible_repr |
236 | + def __repr__(self): |
237 | + return u'Point3D(%d, %d, %d)' % ( |
238 | + self.x, |
239 | + self.y, |
240 | + self.z, |
241 | + ) |
242 | |
243 | === modified file 'autopilot/tests/unit/test_types.py' |
244 | --- autopilot/tests/unit/test_types.py 2013-12-10 20:05:38 +0000 |
245 | +++ autopilot/tests/unit/test_types.py 2014-02-27 02:00:36 +0000 |
246 | @@ -38,8 +38,20 @@ |
247 | Size, |
248 | Time, |
249 | ValueType, |
250 | + _integer_repr, |
251 | + _boolean_repr, |
252 | + _text_repr, |
253 | + _bytes_repr, |
254 | + _dict_repr, |
255 | + _list_repr, |
256 | + _float_repr, |
257 | + _tuple_repr, |
258 | + _get_repr_callable_for_value, |
259 | + _boolean_str, |
260 | + _integer_str, |
261 | ) |
262 | from autopilot.introspection.dbus import DBusIntrospectionObject |
263 | +from autopilot.utilities import compatible_repr |
264 | |
265 | |
266 | class PlainTypeTests(TestWithScenarios, TestCase): |
267 | @@ -81,7 +93,21 @@ |
268 | """repr for PlainType must be the same as the pythonic type.""" |
269 | p = PlainType(self.t(self.v)) |
270 | |
271 | - self.assertThat(repr(p), Equals(repr(self.v))) |
272 | + expected = repr(self.v) |
273 | + expected = expected.rstrip('L') |
274 | + self.assertThat(repr(p), Equals(expected)) |
275 | + |
276 | + def test_str(self): |
277 | + """str(p) for PlainType must be the same as the pythonic type.""" |
278 | + p = PlainType(self.t(self.v)) |
279 | + try: |
280 | + expected = str(self.v) |
281 | + observed = str(p) |
282 | + self.assertEqual(expected, observed) |
283 | + # in Python 2.x, str(u'\2603') *should* raise a UnicodeEncode error: |
284 | + except UnicodeEncodeError: |
285 | + if not six.PY2: |
286 | + raise |
287 | |
288 | def test_wait_for_raises_RuntimeError(self): |
289 | """The wait_for method must raise a RuntimeError if it's called.""" |
290 | @@ -131,6 +157,15 @@ |
291 | |
292 | self.assertThat(r1, Equals(r2)) |
293 | |
294 | + def test_repr(self): |
295 | + expected = repr_type("Rectangle(1, 2, 3, 4)") |
296 | + observed = repr(Rectangle(1, 2, 3, 4)) |
297 | + self.assertEqual(expected, observed) |
298 | + |
299 | + def test_repr_equals_str(self): |
300 | + r = Rectangle(1, 2, 3, 4) |
301 | + self.assertEqual(repr(r), str(r)) |
302 | + |
303 | |
304 | class PointTypeTests(TestCase): |
305 | |
306 | @@ -162,6 +197,15 @@ |
307 | |
308 | self.assertThat(p1, Equals(p2)) |
309 | |
310 | + def test_repr(self): |
311 | + expected = repr_type('Point(1, 2)') |
312 | + observed = repr(Point(1, 2)) |
313 | + self.assertEqual(expected, observed) |
314 | + |
315 | + def test_repr_equals_str(self): |
316 | + p = Point(1, 2) |
317 | + self.assertEqual(repr(p), str(p)) |
318 | + |
319 | |
320 | class SizeTypeTests(TestCase): |
321 | |
322 | @@ -195,6 +239,15 @@ |
323 | |
324 | self.assertThat(s1, Equals(s2)) |
325 | |
326 | + def test_repr(self): |
327 | + expected = repr_type('Size(1, 2)') |
328 | + observed = repr(Size(1, 2)) |
329 | + self.assertEqual(expected, observed) |
330 | + |
331 | + def test_repr_equals_str(self): |
332 | + s = Size(3, 4) |
333 | + self.assertEqual(repr(s), str(s)) |
334 | + |
335 | |
336 | class ColorTypeTests(TestCase): |
337 | |
338 | @@ -230,6 +283,15 @@ |
339 | |
340 | self.assertThat(c1, Equals(c2)) |
341 | |
342 | + def test_repr(self): |
343 | + expected = repr_type('Color(1, 2, 3, 4)') |
344 | + observed = repr(Color(1, 2, 3, 4)) |
345 | + self.assertEqual(expected, observed) |
346 | + |
347 | + def test_repr_equals_str(self): |
348 | + c = Color(255, 255, 255, 0) |
349 | + self.assertEqual(repr(c), str(c)) |
350 | + |
351 | |
352 | class DateTimeTests(TestCase): |
353 | |
354 | @@ -278,6 +340,16 @@ |
355 | |
356 | self.assertThat(dt1.datetime, IsInstance(datetime)) |
357 | |
358 | + def test_repr(self): |
359 | + dt = DateTime(1377209927) |
360 | + expected = repr_type('DateTime(2013-08-22 22:18:47)') |
361 | + observed = repr(dt) |
362 | + self.assertEqual(expected, observed) |
363 | + |
364 | + def test_repr_equals_str(self): |
365 | + dt = DateTime(1377209927) |
366 | + self.assertEqual(repr(dt), str(dt)) |
367 | + |
368 | |
369 | class TimeTests(TestCase): |
370 | |
371 | @@ -322,6 +394,15 @@ |
372 | |
373 | self.assertThat(dt1.time, IsInstance(time)) |
374 | |
375 | + def test_repr(self): |
376 | + expected = repr_type('Time(01:02:03.004)') |
377 | + observed = repr(Time(1, 2, 3, 4)) |
378 | + self.assertEqual(expected, observed) |
379 | + |
380 | + def test_repr_equals_str(self): |
381 | + t = Time(2, 3, 4, 5) |
382 | + self.assertEqual(repr(t), str(t)) |
383 | + |
384 | |
385 | class Point3DTypeTests(TestCase): |
386 | |
387 | @@ -367,6 +448,15 @@ |
388 | |
389 | self.assertThat(p1, NotEquals(p2)) |
390 | |
391 | + def test_repr(self): |
392 | + expected = repr_type('Point3D(1, 2, 3)') |
393 | + observed = repr(Point3D(1, 2, 3)) |
394 | + self.assertEqual(expected, observed) |
395 | + |
396 | + def test_repr_equals_str(self): |
397 | + p3d = Point3D(1, 2, 3) |
398 | + self.assertEqual(repr(p3d), str(p3d)) |
399 | + |
400 | |
401 | class CreateValueInstanceTests(TestCase): |
402 | |
403 | @@ -693,3 +783,128 @@ |
404 | "foo", |
405 | "Cannot create attribute, no data supplied" |
406 | ) |
407 | + |
408 | + |
409 | +class TypeReprTests(TestCase): |
410 | + |
411 | + def test_integer_repr(self): |
412 | + expected = repr_type('42') |
413 | + observed = _integer_repr(42) |
414 | + self.assertEqual(expected, observed) |
415 | + |
416 | + def test_dbus_int_types_all_work(self): |
417 | + expected = repr_type('42') |
418 | + int_types = ( |
419 | + dbus.Byte, |
420 | + dbus.Int16, |
421 | + dbus.Int32, |
422 | + dbus.UInt16, |
423 | + dbus.UInt32, |
424 | + dbus.Int64, |
425 | + dbus.UInt64, |
426 | + ) |
427 | + for t in int_types: |
428 | + observed = _integer_repr(t(42)) |
429 | + self.assertEqual(expected, observed) |
430 | + |
431 | + def test_get_repr_gets_integer_repr_for_all_integer_types(self): |
432 | + int_types = ( |
433 | + dbus.Byte, |
434 | + dbus.Int16, |
435 | + dbus.Int32, |
436 | + dbus.UInt16, |
437 | + dbus.UInt32, |
438 | + dbus.Int64, |
439 | + dbus.UInt64, |
440 | + ) |
441 | + for t in int_types: |
442 | + observed = _get_repr_callable_for_value(t(42)) |
443 | + self.assertEqual(_integer_repr, observed) |
444 | + |
445 | + def test_boolean_repr_true(self): |
446 | + expected = repr_type('True') |
447 | + for values in (True, dbus.Boolean(True)): |
448 | + observed = _boolean_repr(True) |
449 | + self.assertEqual(expected, observed) |
450 | + |
451 | + def test_boolean_repr_false(self): |
452 | + expected = repr_type('False') |
453 | + for values in (False, dbus.Boolean(False)): |
454 | + observed = _boolean_repr(False) |
455 | + self.assertEqual(expected, observed) |
456 | + |
457 | + def test_get_repr_gets_boolean_repr_for_dbus_boolean_type(self): |
458 | + observed = _get_repr_callable_for_value(dbus.Boolean(False)) |
459 | + self.assertEqual(_boolean_repr, observed) |
460 | + |
461 | + def test_text_repr_handles_dbus_string(self): |
462 | + unicode_text = u"plɹoʍ ollǝɥ" |
463 | + observed = _text_repr(dbus.String(unicode_text)) |
464 | + self.assertEqual(repr(unicode_text), observed) |
465 | + |
466 | + def test_text_repr_handles_dbus_object_path(self): |
467 | + path = u"/path/to/some/object" |
468 | + observed = _text_repr(dbus.ObjectPath(path)) |
469 | + self.assertEqual(repr(path), observed) |
470 | + |
471 | + def test_binry_repr_handles_dbys_byte_array(self): |
472 | + data = b'Some bytes' |
473 | + observed = _bytes_repr(dbus.ByteArray(data)) |
474 | + self.assertEqual(repr(data), observed) |
475 | + |
476 | + def test_get_repr_gets_bytes_repr_for_dbus_byte_array(self): |
477 | + observed = _get_repr_callable_for_value(dbus.ByteArray(b'')) |
478 | + self.assertEqual(_bytes_repr, observed) |
479 | + |
480 | + def test_dict_repr_handles_dbus_dictionary(self): |
481 | + token = dict(foo='bar') |
482 | + observed = _dict_repr(dbus.Dictionary(token)) |
483 | + self.assertEqual(repr(token), observed) |
484 | + |
485 | + def test_get_repr_gets_dict_repr_on_dbus_dictionary(self): |
486 | + observed = _get_repr_callable_for_value(dbus.Dictionary(dict())) |
487 | + self.assertEqual(_dict_repr, observed) |
488 | + |
489 | + def test_float_repr_handles_dbus_double(self): |
490 | + token = 1.2345 |
491 | + observed = _float_repr(token) |
492 | + self.assertEqual(repr(token), observed) |
493 | + |
494 | + def test_get_repr_gets_float_repr_on_dbus_double(self): |
495 | + observed = _get_repr_callable_for_value(dbus.Double(0.0)) |
496 | + self.assertEqual(_float_repr, observed) |
497 | + |
498 | + def test_tuple_repr_handles_dbus_struct(self): |
499 | + data = (1, 2, 3) |
500 | + observed = _tuple_repr(dbus.Struct(data)) |
501 | + self.assertEqual(repr(data), observed) |
502 | + |
503 | + def test_get_repr_gets_tuple_repr_on_dbus_struct(self): |
504 | + observed = _get_repr_callable_for_value(dbus.Struct([1])) |
505 | + self.assertEqual(_tuple_repr, observed) |
506 | + |
507 | + def test_list_repr_handles_dbus_array(self): |
508 | + data = [1, 2, 3] |
509 | + observed = _list_repr(dbus.Array(data)) |
510 | + self.assertEqual(repr(data), observed) |
511 | + |
512 | + def test_get_repr_gets_list_repr_on_dbus_array(self): |
513 | + observed = _get_repr_callable_for_value(dbus.Array([1])) |
514 | + self.assertEqual(_list_repr, observed) |
515 | + |
516 | + |
517 | +class TypeStrTests(TestCase): |
518 | + |
519 | + def test_boolean_str_handles_dbus_boolean(self): |
520 | + observed = _boolean_str(dbus.Boolean(False)) |
521 | + self.assertEqual(str(False), observed) |
522 | + |
523 | + def test_integer_str_handles_dbus_byte(self): |
524 | + observed = _integer_str(dbus.Byte(14)) |
525 | + self.assertEqual(str(14), observed) |
526 | + |
527 | + |
528 | +def repr_type(value): |
529 | + """Convert a text or bytes object into the appropriate return type for |
530 | + the __repr__ method.""" |
531 | + return compatible_repr(lambda: value)() |
FAILED: Continuous integration, rev:443 jenkins. qa.ubuntu. com/job/ autopilot- ci/505/ jenkins. qa.ubuntu. com/job/ autopilot- trusty- amd64-ci/ 231/console jenkins. qa.ubuntu. com/job/ autopilot- trusty- armhf-ci/ 231/console jenkins. qa.ubuntu. com/job/ autopilot- trusty- i386-ci/ 140/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- trusty/ 3377/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- amd64/3379/ console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/autopilot- ci/505/ rebuild
http://