File: utilities.py

package info (click to toggle)
python-asciimatics 1.15.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,488 kB
  • sloc: python: 15,713; sh: 8; makefile: 2
file content (185 lines) | stat: -rw-r--r-- 6,102 bytes parent folder | download
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
"""
This module is just a collection of simple helper functions.
"""
from datetime import date, datetime
from logging import getLogger

from asciimatics.constants import SINGLE_LINE, DOUBLE_LINE


# Diagnostic logging
logger = getLogger(__name__)


def readable_mem(mem):
    """
    :param mem: An integer number of bytes to convert to human-readable form.
    :return: A human-readable string representation of the number.
    """
    for suffix in ["", "K", "M", "G", "T"]:
        if mem < 10000:
            return f"{int(mem)}{suffix}"
        mem /= 1024
    return f"{int(mem)}P"


def readable_timestamp(stamp):
    """
    :param stamp: A floating point number representing the POSIX file timestamp.
    :return: A short human-readable string representation of the timestamp.
    """
    if date.fromtimestamp(stamp) == date.today():
        return str(datetime.fromtimestamp(stamp).strftime("%I:%M:%S%p"))
    else:
        return str(date.fromtimestamp(stamp))


class _DotDict(dict):
    """
    Modified dictionary to allow dot notation access.

    This can be used for quick and easy structures.  See https://stackoverflow.com/q/2352181/4994021
    """

    __getattr__ = dict.get
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__


class BoxTool():
    """
    Tool for building boxes out of characters.

    Supports a variety of line styles from `asciimatics.constants`:

    * ``ASCII_LINE`` -- ASCII safe characters (0)
    * ``SINGLE_LINE`` -- Unicode based single lined box (1)
    * ``DOUBLE_LINE`` -- Unicode based double lined box (2)

    Individual characters of a box can be accessed directly through attributes. Most attribute
    names are based on the Extended-ASCII characters used for the UNICODE version of the shape.
    The names describe the directions the piece point in (not the part of the box). For example,
    "up_left" is a corner piece that has a part that points up and a part that points left -- the
    character usually used for the bottom right hand corner of a box.

    Attribute values are:

    * ``up_left`` -- corner piece facing up and left
    * ``up_right`` -- corner piece facing up and right
    * ``down_left`` -- corner piece facing down and left
    * ``down_right`` -- corner piece facing down and right
    * ``h`` -- horizontal line 
    * ``v`` --  vertical line 
    * ``v_inside`` --  vertical line used inside the grid
    * ``v_left`` -- vertical line with mid joiner facing to the left
    * ``v_right`` -- vertical line with mid joiner facing to the right
    * ``h_up`` -- horizontal line with a mid joiner facing up
    * ``h_down`` -- horizontal line with a mid joiner facing down
    * ``cross`` -- intersection between vertical and horizontal
    """

    def __init__(self, unicode_aware, style=SINGLE_LINE):
        """
        :param unicode_aware: boolean indicating if the terminal is Unicode
            aware. If False, will force the use of the ASCII style
        :param style: line style specifier. Supports ``ASCII_LINE``,
            ``SINGLE_LINE``, and ``DOUBLE_LINE``. Defaults to ``SINGLE_LINE``.
        """
        self.unicode_aware = unicode_aware

        # Call property to get side-effect of setting values
        self.style = style

    @property
    def style(self):
        """
        The line drawing style used to draw boxes. Possible styles are set
        in :mod:`asciimatics.constants`.

        :param style: One of ``ASCII_LINE``, ``SINGLE_LINE``, or ``DOUBLE_LINE``
        """
        return self._style

    @style.setter
    def style(self, style):
        self._style = style

        if style == SINGLE_LINE and self.unicode_aware:
            self.down_right = "┌"
            self.down_left = "┐"
            self.up_right = "└"
            self.up_left = "┘"
            self.h = "─"
            self.h_inside = "─"
            self.v = "│"
            self.v_inside = "│"
            self.v_left = "┤"
            self.v_right = "├"
            self.h_up = "┴"
            self.h_down = "┬"
            self.cross = "┼"
        elif style == DOUBLE_LINE and self.unicode_aware:
            self.down_right = "╔"
            self.down_left = "╗"
            self.up_right = "╚"
            self.up_left = "╝"
            self.h = "═"
            self.h_inside = "═"
            self.v = "║"
            self.v_inside = "║"
            self.v_left = "╣"
            self.v_right = "╠"
            self.h_up = "╩"
            self.h_down = "╦"
            self.cross = "╬"
        else:
            self.down_left = "+"
            self.down_right = "+"
            self.up_right = "+"
            self.up_left = "+"
            self.h = "-"
            self.h_inside = "-"
            self.v = "|"
            self.v_inside = ":"
            self.v_left = "+"
            self.v_right = "+"
            self.h_up = "+"
            self.h_down = "+"
            self.cross = "+"

    # --- Empty box methods
    def box_top(self, width):
        """
        Returns a string containing the top border of a box

        :param width: width of box, including corners
        """
        return self.down_right + (width - 2) * self.h + self.down_left

    def box_bottom(self, width):
        """
        Returns a string containing the bottom border of a box

        :param width: width of box, including corners
        """
        return self.up_right + (width - 2) * self.h + self.up_left

    def box_line(self, width):
        """
        Returns a string with a vertical bar on each end, padded with
        spaces in between for the given width.

        :param width: width of box including sides
        """
        return self.v + (width - 2) * ' ' + self.v

    def box(self, width, height):
        """
        Returns a string containing a box with the given width and height.
        """
        lines = [self.box_top(width)]
        for _ in range(height - 2):
            lines.append(self.box_line(width))

        lines.append(self.box_bottom(width))
        return '\n'.join(lines) + '\n'