cs-x 20261016__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cs_x-20261016/PKG-INFO +98 -0
- cs_x-20261016/pyproject.toml +123 -0
- cs_x-20261016/src/cs/x.py +182 -0
cs_x-20261016/PKG-INFO
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cs-x
|
|
3
|
+
Version: 20261016
|
|
4
|
+
Summary: X(), for low level debugging.
|
|
5
|
+
Keywords: python2,python3
|
|
6
|
+
Author-email: Cameron Simpson <cs@cskk.id.au>
|
|
7
|
+
Requires-Python: >=3
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Classifier: Programming Language :: Python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
16
|
+
Requires-Dist: cs.ansi_colour>=20260531
|
|
17
|
+
Requires-Dist: cs.gimmicks>=20260311
|
|
18
|
+
Project-URL: MonoRepo Commits, https://bitbucket.org/cameron_simpson/css/commits/branch/main
|
|
19
|
+
Project-URL: Monorepo Git Mirror, https://github.com/cameron-simpson/css
|
|
20
|
+
Project-URL: Monorepo Hg/Mercurial Mirror, https://hg.sr.ht/~cameron-simpson/css
|
|
21
|
+
Project-URL: Source, https://github.com/cameron-simpson/css/blob/main/lib/python/cs/x.py
|
|
22
|
+
|
|
23
|
+
X(), for low level debugging.
|
|
24
|
+
|
|
25
|
+
X() is my function for low level ad hoc debug messages.
|
|
26
|
+
It takes a message and optional format arguments for use with `%`.
|
|
27
|
+
It is presented here in its own module for reuse:
|
|
28
|
+
|
|
29
|
+
from cs.x import X
|
|
30
|
+
...
|
|
31
|
+
X("foo: x=%s, a=%r", x, a)
|
|
32
|
+
|
|
33
|
+
It normally writes directly to `sys.stderr` but accepts an optional
|
|
34
|
+
keyword argument `file` to specify a different filelike object.
|
|
35
|
+
|
|
36
|
+
The following globals further tune its behaviour,
|
|
37
|
+
absent the `file=` parameter:
|
|
38
|
+
* `X_default_colour`: if set, messages will be ANSI coloured using
|
|
39
|
+
`cs.ansi_colour.colourise`
|
|
40
|
+
* `X_discard`: if true then discard the message.
|
|
41
|
+
Otherwise write the message to `sys.stderr`.
|
|
42
|
+
`X_discard`'s default value is `not sys.stderr.isatty()`.
|
|
43
|
+
* `X_logger`: if not `None` then log a warning to that logger.
|
|
44
|
+
* `X_via_tty`: if true then a pathname to which to append messages.
|
|
45
|
+
|
|
46
|
+
The following environment variables affect the initial values of the globals:
|
|
47
|
+
* `$CS_X_COLOUR`: this sets `X_default_colour`.
|
|
48
|
+
* `$CS_X_LOGGER`:
|
|
49
|
+
if present, an empty value sets `X_logger` to the root logger
|
|
50
|
+
and a nonempty value names a logger.
|
|
51
|
+
* `$CS_X_VIA_TTY`: if missing or empty, `X_via_tty` will be false.
|
|
52
|
+
Otherwise,
|
|
53
|
+
if `$CS_X_VIA_TTY` has a nonempty value which is a full path
|
|
54
|
+
to an existing filesystem object (typically a tty)
|
|
55
|
+
then is will be used for `X_via_tty`,
|
|
56
|
+
otherwise `X_via_tty` will be set to `'/dev/tty'`.
|
|
57
|
+
This is handy for getting debugging out of test suites,
|
|
58
|
+
which often divert `sys.stderr`.
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
Short summary:
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
* `X`: Unconditionally write the message `msg`.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
* `Y`: Wrapper for `X()` rendering in yellow.
|
|
69
|
+
|
|
70
|
+
# Functions
|
|
71
|
+
|
|
72
|
+
## X(msg, *args, file=None, colour=None)
|
|
73
|
+
|
|
74
|
+
Unconditionally write the message `msg`.
|
|
75
|
+
|
|
76
|
+
If there are positional arguments after `msg`,
|
|
77
|
+
format `msg` using %-expansion with those arguments.
|
|
78
|
+
|
|
79
|
+
Keyword arguments:
|
|
80
|
+
* `file`: optional keyword argument specifying the output file.
|
|
81
|
+
* `colour`: optional text colour.
|
|
82
|
+
If specified, surround the message with ANSI escape sequences
|
|
83
|
+
to render the text in that colour.
|
|
84
|
+
|
|
85
|
+
If `file` is not `None`, write to it unconditionally.
|
|
86
|
+
Otherwise, the following globals are consulted in order:
|
|
87
|
+
* `X_logger`: if not `None` then log a warning to that logger
|
|
88
|
+
* `X_via_tty`: if true then append the message to the path it contains
|
|
89
|
+
* `X_discard`: if true then discard the message
|
|
90
|
+
Otherwise write the message to `sys.stderr`.
|
|
91
|
+
|
|
92
|
+
`X_logger` is `None` by default.
|
|
93
|
+
`X_via_tty` is initialised from the environment variable `$CS_X_VIA_TTY`.
|
|
94
|
+
`X_discard` is true unless `sys.stderr.isatty()` is true.
|
|
95
|
+
|
|
96
|
+
## Y(msg, *a, **kw)
|
|
97
|
+
|
|
98
|
+
Wrapper for `X()` rendering in yellow.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "cs-x"
|
|
3
|
+
description = "X(), for low level debugging."
|
|
4
|
+
authors = [
|
|
5
|
+
{ name = "Cameron Simpson", email = "cs@cskk.id.au" },
|
|
6
|
+
]
|
|
7
|
+
keywords = [
|
|
8
|
+
"python2",
|
|
9
|
+
"python3",
|
|
10
|
+
]
|
|
11
|
+
dependencies = [
|
|
12
|
+
"cs.ansi_colour>=20260531",
|
|
13
|
+
"cs.gimmicks>=20260311",
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
22
|
+
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
|
23
|
+
]
|
|
24
|
+
version = "20261016"
|
|
25
|
+
requires-python = ">=3"
|
|
26
|
+
|
|
27
|
+
[project.license]
|
|
28
|
+
text = "GNU General Public License v3 or later (GPLv3+)"
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
"Monorepo Hg/Mercurial Mirror" = "https://hg.sr.ht/~cameron-simpson/css"
|
|
32
|
+
"Monorepo Git Mirror" = "https://github.com/cameron-simpson/css"
|
|
33
|
+
"MonoRepo Commits" = "https://bitbucket.org/cameron_simpson/css/commits/branch/main"
|
|
34
|
+
Source = "https://github.com/cameron-simpson/css/blob/main/lib/python/cs/x.py"
|
|
35
|
+
|
|
36
|
+
[project.readme]
|
|
37
|
+
text = """
|
|
38
|
+
X(), for low level debugging.
|
|
39
|
+
|
|
40
|
+
X() is my function for low level ad hoc debug messages.
|
|
41
|
+
It takes a message and optional format arguments for use with `%`.
|
|
42
|
+
It is presented here in its own module for reuse:
|
|
43
|
+
|
|
44
|
+
from cs.x import X
|
|
45
|
+
...
|
|
46
|
+
X(\"foo: x=%s, a=%r\", x, a)
|
|
47
|
+
|
|
48
|
+
It normally writes directly to `sys.stderr` but accepts an optional
|
|
49
|
+
keyword argument `file` to specify a different filelike object.
|
|
50
|
+
|
|
51
|
+
The following globals further tune its behaviour,
|
|
52
|
+
absent the `file=` parameter:
|
|
53
|
+
* `X_default_colour`: if set, messages will be ANSI coloured using
|
|
54
|
+
`cs.ansi_colour.colourise`
|
|
55
|
+
* `X_discard`: if true then discard the message.
|
|
56
|
+
Otherwise write the message to `sys.stderr`.
|
|
57
|
+
`X_discard`'s default value is `not sys.stderr.isatty()`.
|
|
58
|
+
* `X_logger`: if not `None` then log a warning to that logger.
|
|
59
|
+
* `X_via_tty`: if true then a pathname to which to append messages.
|
|
60
|
+
|
|
61
|
+
The following environment variables affect the initial values of the globals:
|
|
62
|
+
* `$CS_X_COLOUR`: this sets `X_default_colour`.
|
|
63
|
+
* `$CS_X_LOGGER`:
|
|
64
|
+
if present, an empty value sets `X_logger` to the root logger
|
|
65
|
+
and a nonempty value names a logger.
|
|
66
|
+
* `$CS_X_VIA_TTY`: if missing or empty, `X_via_tty` will be false.
|
|
67
|
+
Otherwise,
|
|
68
|
+
if `$CS_X_VIA_TTY` has a nonempty value which is a full path
|
|
69
|
+
to an existing filesystem object (typically a tty)
|
|
70
|
+
then is will be used for `X_via_tty`,
|
|
71
|
+
otherwise `X_via_tty` will be set to `'/dev/tty'`.
|
|
72
|
+
This is handy for getting debugging out of test suites,
|
|
73
|
+
which often divert `sys.stderr`.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
Short summary:
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
* `X`: Unconditionally write the message `msg`.
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
* `Y`: Wrapper for `X()` rendering in yellow.
|
|
84
|
+
|
|
85
|
+
# Functions
|
|
86
|
+
|
|
87
|
+
## X(msg, *args, file=None, colour=None)
|
|
88
|
+
|
|
89
|
+
Unconditionally write the message `msg`.
|
|
90
|
+
|
|
91
|
+
If there are positional arguments after `msg`,
|
|
92
|
+
format `msg` using %-expansion with those arguments.
|
|
93
|
+
|
|
94
|
+
Keyword arguments:
|
|
95
|
+
* `file`: optional keyword argument specifying the output file.
|
|
96
|
+
* `colour`: optional text colour.
|
|
97
|
+
If specified, surround the message with ANSI escape sequences
|
|
98
|
+
to render the text in that colour.
|
|
99
|
+
|
|
100
|
+
If `file` is not `None`, write to it unconditionally.
|
|
101
|
+
Otherwise, the following globals are consulted in order:
|
|
102
|
+
* `X_logger`: if not `None` then log a warning to that logger
|
|
103
|
+
* `X_via_tty`: if true then append the message to the path it contains
|
|
104
|
+
* `X_discard`: if true then discard the message
|
|
105
|
+
Otherwise write the message to `sys.stderr`.
|
|
106
|
+
|
|
107
|
+
`X_logger` is `None` by default.
|
|
108
|
+
`X_via_tty` is initialised from the environment variable `$CS_X_VIA_TTY`.
|
|
109
|
+
`X_discard` is true unless `sys.stderr.isatty()` is true.
|
|
110
|
+
|
|
111
|
+
## Y(msg, *a, **kw)
|
|
112
|
+
|
|
113
|
+
Wrapper for `X()` rendering in yellow."""
|
|
114
|
+
content-type = "text/markdown"
|
|
115
|
+
|
|
116
|
+
[build-system]
|
|
117
|
+
build-backend = "flit_core.buildapi"
|
|
118
|
+
requires = [
|
|
119
|
+
"flit_core >=3.2,<4",
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
[tool.flit.module]
|
|
123
|
+
name = "cs.x"
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
#
|
|
3
|
+
# Just my X debugging function.
|
|
4
|
+
# - Cameron Simpson <cs@cskk.id.au>
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
'''
|
|
8
|
+
X(), for low level debugging.
|
|
9
|
+
|
|
10
|
+
X() is my function for low level ad hoc debug messages.
|
|
11
|
+
It takes a message and optional format arguments for use with `%`.
|
|
12
|
+
It is presented here in its own module for reuse:
|
|
13
|
+
|
|
14
|
+
from cs.x import X
|
|
15
|
+
...
|
|
16
|
+
X("foo: x=%s, a=%r", x, a)
|
|
17
|
+
|
|
18
|
+
It normally writes directly to `sys.stderr` but accepts an optional
|
|
19
|
+
keyword argument `file` to specify a different filelike object.
|
|
20
|
+
|
|
21
|
+
The following globals further tune its behaviour,
|
|
22
|
+
absent the `file=` parameter:
|
|
23
|
+
* `X_default_colour`: if set, messages will be ANSI coloured using
|
|
24
|
+
`cs.ansi_colour.colourise`
|
|
25
|
+
* `X_discard`: if true then discard the message.
|
|
26
|
+
Otherwise write the message to `sys.stderr`.
|
|
27
|
+
`X_discard`'s default value is `not sys.stderr.isatty()`.
|
|
28
|
+
* `X_logger`: if not `None` then log a warning to that logger.
|
|
29
|
+
* `X_via_tty`: if true then a pathname to which to append messages.
|
|
30
|
+
|
|
31
|
+
The following environment variables affect the initial values of the globals:
|
|
32
|
+
* `$CS_X_COLOUR`: this sets `X_default_colour`.
|
|
33
|
+
* `$CS_X_LOGGER`:
|
|
34
|
+
if present, an empty value sets `X_logger` to the root logger
|
|
35
|
+
and a nonempty value names a logger.
|
|
36
|
+
* `$CS_X_VIA_TTY`: if missing or empty, `X_via_tty` will be false.
|
|
37
|
+
Otherwise,
|
|
38
|
+
if `$CS_X_VIA_TTY` has a nonempty value which is a full path
|
|
39
|
+
to an existing filesystem object (typically a tty)
|
|
40
|
+
then is will be used for `X_via_tty`,
|
|
41
|
+
otherwise `X_via_tty` will be set to `'/dev/tty'`.
|
|
42
|
+
This is handy for getting debugging out of test suites,
|
|
43
|
+
which often divert `sys.stderr`.
|
|
44
|
+
'''
|
|
45
|
+
|
|
46
|
+
import logging
|
|
47
|
+
import os
|
|
48
|
+
import os.path
|
|
49
|
+
import sys
|
|
50
|
+
|
|
51
|
+
from cs.ansi_colour import colourise
|
|
52
|
+
from cs.gimmicks import open_append
|
|
53
|
+
|
|
54
|
+
__version__ = '20261016'
|
|
55
|
+
|
|
56
|
+
DISTINFO = {
|
|
57
|
+
'keywords': ["python2", "python3"],
|
|
58
|
+
'classifiers': [
|
|
59
|
+
"Programming Language :: Python",
|
|
60
|
+
"Programming Language :: Python :: 3",
|
|
61
|
+
],
|
|
62
|
+
'install_requires': [
|
|
63
|
+
'cs.ansi_colour',
|
|
64
|
+
'cs.gimmicks',
|
|
65
|
+
],
|
|
66
|
+
'python_requires':
|
|
67
|
+
'>=3',
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# discard output? the default if sys.stderr is not a tty
|
|
71
|
+
try:
|
|
72
|
+
isatty = sys.stderr.isatty
|
|
73
|
+
except AttributeError:
|
|
74
|
+
X_discard = True
|
|
75
|
+
else:
|
|
76
|
+
X_discard = not isatty()
|
|
77
|
+
# set to a logger to log as a warning
|
|
78
|
+
X_logger = os.environ.get('CS_X_LOGGER')
|
|
79
|
+
if X_logger is not None:
|
|
80
|
+
X_Logger = logging.getLogger(X_logger or None)
|
|
81
|
+
# colouring
|
|
82
|
+
X_default_colour = os.environ.get('CS_X_COLOUR')
|
|
83
|
+
|
|
84
|
+
# pylint: disable=too-many-branches
|
|
85
|
+
def X(msg, *args, file=None, colour=None): # noqa: N802
|
|
86
|
+
''' Unconditionally write the message `msg`.
|
|
87
|
+
|
|
88
|
+
If there are positional arguments after `msg`,
|
|
89
|
+
format `msg` using %-expansion with those arguments.
|
|
90
|
+
|
|
91
|
+
Keyword arguments:
|
|
92
|
+
* `file`: optional keyword argument specifying the output file.
|
|
93
|
+
* `colour`: optional text colour.
|
|
94
|
+
If specified, surround the message with ANSI escape sequences
|
|
95
|
+
to render the text in that colour.
|
|
96
|
+
|
|
97
|
+
If `file` is not `None`, write to it unconditionally.
|
|
98
|
+
Otherwise, the following globals are consulted in order:
|
|
99
|
+
* `X_logger`: if not `None` then log a warning to that logger
|
|
100
|
+
* `X_via_tty`: if true then append the message to the path it contains
|
|
101
|
+
* `X_discard`: if true then discard the message
|
|
102
|
+
Otherwise write the message to `sys.stderr`.
|
|
103
|
+
|
|
104
|
+
`X_logger` is `None` by default.
|
|
105
|
+
`X_via_tty` is initialised from the environment variable `$CS_X_VIA_TTY`.
|
|
106
|
+
`X_discard` is true unless `sys.stderr.isatty()` is true.
|
|
107
|
+
'''
|
|
108
|
+
if colour is None:
|
|
109
|
+
colour = X_default_colour
|
|
110
|
+
if args:
|
|
111
|
+
try:
|
|
112
|
+
msg = msg % args
|
|
113
|
+
except TypeError as e:
|
|
114
|
+
X("X(%r, *%r): %s", msg, args, e, colour='red', file=file)
|
|
115
|
+
msg = f'{msg} % {args!r}'
|
|
116
|
+
else:
|
|
117
|
+
msg = str(msg)
|
|
118
|
+
if colour:
|
|
119
|
+
msg = colourise(msg, colour=colour)
|
|
120
|
+
close_fp = None
|
|
121
|
+
if file is None:
|
|
122
|
+
if X_logger:
|
|
123
|
+
# NB: ignores any kwargs
|
|
124
|
+
X_logger.warning(msg)
|
|
125
|
+
return
|
|
126
|
+
if X_via_tty:
|
|
127
|
+
# NB: ignores any kwargs
|
|
128
|
+
try:
|
|
129
|
+
f = open_append(X_via_tty)
|
|
130
|
+
except (IOError, OSError) as e: # noqa: UP024
|
|
131
|
+
X(
|
|
132
|
+
"X: cannot append to %r: %s:%s",
|
|
133
|
+
X_via_tty,
|
|
134
|
+
type(e),
|
|
135
|
+
e,
|
|
136
|
+
file=sys.stderr,
|
|
137
|
+
)
|
|
138
|
+
X(msg, file=sys.stderr)
|
|
139
|
+
return
|
|
140
|
+
close_fp = f
|
|
141
|
+
if X_discard:
|
|
142
|
+
return
|
|
143
|
+
file = sys.stderr
|
|
144
|
+
print(msg, file=file)
|
|
145
|
+
if close_fp is not None:
|
|
146
|
+
close_fp.close()
|
|
147
|
+
|
|
148
|
+
# init X_via_tty (after X() because we use X() for messaging)
|
|
149
|
+
env_via_tty = os.environ.get('CS_X_VIA_TTY', '')
|
|
150
|
+
if not env_via_tty:
|
|
151
|
+
X_via_tty = False
|
|
152
|
+
else:
|
|
153
|
+
X_via_tty = '/dev/tty'
|
|
154
|
+
if env_via_tty.startswith('/'):
|
|
155
|
+
try:
|
|
156
|
+
xfd = os.open(env_via_tty, os.O_RDONLY)
|
|
157
|
+
except OSError as e:
|
|
158
|
+
X("%s: open(%r): %s, using %r", __file__, env_via_tty, e, X_via_tty)
|
|
159
|
+
else:
|
|
160
|
+
if not os.isatty(xfd):
|
|
161
|
+
X(
|
|
162
|
+
"%s: open(%r): not a tty, using %r",
|
|
163
|
+
__file__,
|
|
164
|
+
env_via_tty,
|
|
165
|
+
X_via_tty,
|
|
166
|
+
)
|
|
167
|
+
else:
|
|
168
|
+
X_via_tty = env_via_tty
|
|
169
|
+
os.close(xfd)
|
|
170
|
+
|
|
171
|
+
if os.environ.get('CS_X_BUILTIN', ''):
|
|
172
|
+
try:
|
|
173
|
+
import builtins
|
|
174
|
+
except ImportError:
|
|
175
|
+
pass
|
|
176
|
+
else:
|
|
177
|
+
builtins.X = X
|
|
178
|
+
|
|
179
|
+
def Y(msg, *a, **kw): # noqa: N802
|
|
180
|
+
''' Wrapper for `X()` rendering in yellow.
|
|
181
|
+
'''
|
|
182
|
+
X(msg, *a, colour='yellow', **kw)
|