forked from cool-RR/python_toolbox
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsys_tools.py
More file actions
121 lines (84 loc) · 3.32 KB
/
sys_tools.py
File metadata and controls
121 lines (84 loc) · 3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# Copyright 2009-2017 Ram Rachum.
# This program is distributed under the MIT license.
'''Defines various `sys`-related tools.'''
from __future__ import generator_stop
import sys
import pathlib
import io
from python_toolbox.context_management import (ContextManager,
BlankContextManager)
from python_toolbox.temp_value_setting import TempValueSetter
from python_toolbox.reasoned_bool import ReasonedBool
from python_toolbox import sequence_tools
class OutputCapturer(ContextManager):
'''
Context manager for catching all system output generated during suite.
Example:
with OutputCapturer() as output_capturer:
print('woo!')
assert output_capturer.output == 'woo!\n'
The boolean arguments `stdout` and `stderr` determine, respectively,
whether the standard-output and the standard-error streams will be
captured.
'''
def __init__(self, stdout=True, stderr=True):
self.string_io = io.StringIO()
if stdout:
self._stdout_temp_setter = \
TempValueSetter((sys, 'stdout'), self.string_io)
else: # not stdout
self._stdout_temp_setter = BlankContextManager()
if stderr:
self._stderr_temp_setter = \
TempValueSetter((sys, 'stderr'), self.string_io)
else: # not stderr
self._stderr_temp_setter = BlankContextManager()
def manage_context(self):
'''Manage the `OutputCapturer`'s context.'''
with self._stdout_temp_setter, self._stderr_temp_setter:
yield self
output = property(lambda self: self.string_io.getvalue(),
doc='''The string of output that was captured.''')
class TempSysPathAdder(ContextManager):
'''
Context manager for temporarily adding paths to `sys.path`.
Removes the path(s) after suite.
Example:
with TempSysPathAdder('path/to/fubar/package'):
import fubar
fubar.do_stuff()
'''
def __init__(self, addition):
'''
Construct the `TempSysPathAdder`.
`addition` may be a path or a sequence of paths.
'''
self.addition = map(
str,
sequence_tools.to_tuple(addition,
item_type=(str, pathlib.PurePath))
)
def __enter__(self):
self.entries_not_in_sys_path = [entry for entry in self.addition if
entry not in sys.path]
sys.path += self.entries_not_in_sys_path
return self
def __exit__(self, *args, **kwargs):
for entry in self.entries_not_in_sys_path:
# We don't allow anyone to remove it except for us:
assert entry in sys.path
sys.path.remove(entry)
frozen = getattr(sys, 'frozen', None)
'''
The "frozen string", if we are frozen, otherwise `None`.
This is useful for checking if we are frozen, e.g. with py2exe.
'''
is_pypy = ('__pypy__' in sys.builtin_module_names)
can_import_compiled_modules = \
ReasonedBool(False, "Pypy can't import compiled "
"modules by default") if is_pypy else True
# May want in future:
#def execute(command):
#with OutputCapturer() as output_capturer:
#subprocess.Popen(command, shell=True)
#return output_capturer.output