Commit d6ffbaa57eec3203e4fd358e6b71a43190dc5b06
1 parent
6956fce2
unittest: fix bug with OutputCapture and old loggers
Showing
1 changed file
with
20 additions
and
0 deletions
tests/test_utils/output_capture.py
| @@ -2,13 +2,20 @@ | @@ -2,13 +2,20 @@ | ||
| 2 | 2 | ||
| 3 | from __future__ import print_function | 3 | from __future__ import print_function |
| 4 | import sys | 4 | import sys |
| 5 | +import logging | ||
| 5 | 6 | ||
| 6 | 7 | ||
| 7 | # python 2/3 version conflict: | 8 | # python 2/3 version conflict: |
| 8 | if sys.version_info.major <= 2: | 9 | if sys.version_info.major <= 2: |
| 9 | from StringIO import StringIO | 10 | from StringIO import StringIO |
| 11 | + # reload is a builtin | ||
| 10 | else: | 12 | else: |
| 11 | from io import StringIO | 13 | from io import StringIO |
| 14 | + if sys.version_info.minor < 4: | ||
| 15 | + from imp import reload | ||
| 16 | + else: | ||
| 17 | + from importlib import reload | ||
| 18 | + | ||
| 12 | 19 | ||
| 13 | class OutputCapture: | 20 | class OutputCapture: |
| 14 | """ context manager that captures stdout | 21 | """ context manager that captures stdout |
| @@ -24,6 +31,10 @@ class OutputCapture: | @@ -24,6 +31,10 @@ class OutputCapture: | ||
| 24 | # ...or test all output in one go | 31 | # ...or test all output in one go |
| 25 | some_test(capturer.get_data()) | 32 | some_test(capturer.get_data()) |
| 26 | 33 | ||
| 34 | + In order to solve issues with old logger instances still remembering closed | ||
| 35 | + StringIO instances as "their" stdout, logging is shutdown and restarted | ||
| 36 | + upon entering this Context Manager. This means that you may have to reload | ||
| 37 | + your module, as well. | ||
| 27 | """ | 38 | """ |
| 28 | 39 | ||
| 29 | def __init__(self): | 40 | def __init__(self): |
| @@ -32,6 +43,11 @@ class OutputCapture: | @@ -32,6 +43,11 @@ class OutputCapture: | ||
| 32 | self.data = None | 43 | self.data = None |
| 33 | 44 | ||
| 34 | def __enter__(self): | 45 | def __enter__(self): |
| 46 | + # Avoid problems with old logger instances that still remember an old | ||
| 47 | + # closed StringIO as their sys.stdout | ||
| 48 | + logging.shutdown() | ||
| 49 | + reload(logging) | ||
| 50 | + | ||
| 35 | # replace sys.stdout with own buffer. | 51 | # replace sys.stdout with own buffer. |
| 36 | self.orig_stdout = sys.stdout | 52 | self.orig_stdout = sys.stdout |
| 37 | sys.stdout = self.buffer | 53 | sys.stdout = self.buffer |
| @@ -61,3 +77,7 @@ class OutputCapture: | @@ -61,3 +77,7 @@ class OutputCapture: | ||
| 61 | def __iter__(self): | 77 | def __iter__(self): |
| 62 | for line in self.get_data().splitlines(): | 78 | for line in self.get_data().splitlines(): |
| 63 | yield line | 79 | yield line |
| 80 | + | ||
| 81 | + def reload_module(self, mod): | ||
| 82 | + """ Wrapper around reload function for different python versions """ | ||
| 83 | + return reload(mod) |