forked from behave/behave.example
/
baseterm.py
140 lines (116 loc) · 4.44 KB
/
baseterm.py
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# -*- coding: utf-8 -*-
"""
This module provides functionality to automatically select the best
matching terminal for your platform or operating system.
"""
from __future__ import absolute_import
import sys
# -----------------------------------------------------------------------------
# EXCEPTIONS:
# -----------------------------------------------------------------------------
class UnknownStyleError(KeyError):
"""
Raised when a name text style is unknown/not found.
"""
# -----------------------------------------------------------------------------
# FUNCTIONS:
# -----------------------------------------------------------------------------
def isatty(stream):
return hasattr(stream, "isatty") and stream.isatty()
# -----------------------------------------------------------------------------
# CLASS: BaseTerminalWriter
# -----------------------------------------------------------------------------
class UnstyledWriter(object):
def __init__(self, _, file=None):
if file is None:
file = sys.stdout
self.file = file
def write(self, text):
self.file.write(text)
class BaseTerminalWriter(object):
"""
Provides the core functionality for a terminal writer that
supports text styles in a coloring/non-coloring terminal.
for behave that supports text output with text styles and style attributes.
.. code-block:: python
terminal = MyTerminalWriter(sys.stdout)
terminal.write("Normal Text without styling")
terminal.write("STYLED_TEXT", style="passed")
"""
style_writer_class = UnstyledWriter
default_stylesheet = None
def __init__(self, stream=None, stylesheet=None, **kwargs):
if stream is None:
stream = sys.stdout
self.stream = stream
self.colored = kwargs.get("colored", False)
self.styles = {}
stylesheet = stylesheet or self.default_stylesheet
if stylesheet:
self.setup_styles(stylesheet)
@property
def styled(self):
return bool(self.styles)
def add_style(self, name, style_description):
style_writer_class = self.style_writer_class
self.styles[name] = style_writer_class(style_description, self.stream)
def setup_styles(self, stylesheet):
for name, style_description in stylesheet.items():
self.add_style(name, style_description)
def has_feature(self, feature):
# -- FEATURES: cursor_up, colored
if feature == "cursor_up":
return hasattr(self, "move_cursor_up")
return bool(getattr(self, feature, False))
# -- STREAM-LIKE API:
def write(self, text, style=None):
if not text:
return
elif not style:
# -- CASE: Write text w/o styling attributes (normal style).
return self.stream.write(text)
# -- CASE: Write text w/ style attributes.
style_writer = self.styles.get(style, None)
if not style_writer:
raise UnknownStyleError(style)
style_writer.write(text)
def flush(self):
self.stream.flush()
#def close(self):
# self.flush()
# self.stream.close()
#
def isatty(self):
"""Indicates if this terminal (stream) is a TTY."""
return isatty(self.stream)
def __getattr__(self, name):
"""
Transparent stream-proxy functionality.
Provides direct access to stream attributes and methods, like:
* stream.closed
* stream.encoding
* ...
"""
# -- TRANSPARENT-PROXY: To stream
attrib_func = getattr(self.stream, name, None)
if attrib_func:
return attrib_func
raise AttributeError(name)
# -----------------------------------------------------------------------------
# CLASS: PlainTerminal
# -----------------------------------------------------------------------------
class PlainTerminalWriter(BaseTerminalWriter):
"""
Provides a basic terminal without coloring and style support.
Therefore, all styled text writes are just passed through without styling.
"""
def __init__(self, file=None, **kwargs):
assert not kwargs.get("colored", None)
super(PlainTerminalWriter, self).__init__(file, **kwargs)
assert not self.colored
def write(self, text, style=None):
"""
Overwrite base class implementation to ignore all style settings.
Writes only the text.
"""
self.stream.write(text)