jc-debug 1.0.2__tar.gz → 1.0.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jc-debug
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: Makes debugging to the console both simpler and much more powerful.
5
5
  Author-email: Jeff Clough <jeff@cloughcottage.com>
6
6
  License: MIT License
@@ -42,8 +42,8 @@ Dynamic: license-file
42
42
 
43
43
  # debug
44
44
 
45
- This debug module a class named DebugChannel, instances of which are
46
- useful for adding temporary or conditional debug output to CLI scripts.
45
+ This debug module a class named DebugChannel, instances of which are useful for
46
+ adding temporary or conditional debug output to CLI scripts.
47
47
 
48
48
  The minimal boilerplate is pretty simple:
49
49
 
@@ -53,9 +53,9 @@ from debug import DebugChannel
53
53
  dc=DebugChannel(True)
54
54
  ```
55
55
 
56
- By default, DebugChannels are created disabled (the write no output), so
57
- the `True` above enables `dc` during its instantiation so it needn't be
58
- enabled later.
56
+ By default, DebugChannels are created disabled (the write no output), so the
57
+ `True` above enables `dc` during its instantiation so it needn't be enabled
58
+ later.
59
59
 
60
60
  A more common way of handling this is ...
61
61
 
@@ -73,18 +73,18 @@ dc.enable(opt.debug)
73
73
  ...
74
74
  ```
75
75
 
76
- This enables the `dc` DebugChannel instance only if --debug is given on
77
- the script's command line.
76
+ This enables the `dc` DebugChannel instance only if --debug is given on the
77
+ script's command line.
78
78
 
79
79
  By default, output is sent to stdandard error and formatted as:
80
80
 
81
81
  '{label}: [{pid}] {basename}:{line}:{function}: {indent}{message}\n'
82
82
 
83
- There are several variables you can include in DebugChannel's output.
84
- See the DebugChannel docs below for a list.
83
+ There are several variables you can include in DebugChannel's output. See the
84
+ DebugChannel docs below for a list.
85
85
 
86
- So, for example, if you want to see how your variables are behaving in a
87
- loop, you might do something like this:
86
+ So, for example, if you want to see how your variables are behaving in a loop,
87
+ you might do something like this:
88
88
 
89
89
  ```python
90
90
  from debug import DebugChannel
@@ -96,15 +96,15 @@ dc=DebugChannel(
96
96
 
97
97
  dc("Entering loop ...").indent()
98
98
  for i in range(5):
99
- dc(f"i={i}").indent()
99
+ dc(f"{i=}").indent()
100
100
  for j in range(3):
101
- dc(f"j={j}")
101
+ dc(f"{j=}")
102
102
  dc.undent()("Done with j loop.")
103
103
  dc.undent()("Done with i loop.")
104
104
  ```
105
105
 
106
- That gives you this necely indented output. The indent() and undent()
107
- methods are one thing that makes DebugChannels so nice to work with.
106
+ That gives you this necely indented output. The indent() and undent() methods
107
+ are one thing that makes DebugChannels so nice to work with.
108
108
 
109
109
  DC: 8: Entering loop ...
110
110
  DC: 10: i=0
@@ -134,8 +134,8 @@ methods are one thing that makes DebugChannels so nice to work with.
134
134
  DC: 13: Done with j loop.
135
135
  DC: 14: Done with i loop.
136
136
 
137
- That's a simple example, but you might be starting to get an idea of
138
- how versatile DebugChannel instances can be.
137
+ That's a simple example, but you might be starting to get an idea of how
138
+ versatile DebugChannel instances can be.
139
139
 
140
140
  A DebugChannel can also be used as a function decorator:
141
141
 
@@ -163,9 +163,9 @@ example2("First test",3)
163
163
  example2("Second test",2)
164
164
  ```
165
165
 
166
- This causes entry into and exit from the decorated function to be
167
- recorded in the given DebugChannel's output. If you put that into a file
168
- named foo.py and then run "python3 -m foo", you'll get this:
166
+ This causes entry into and exit from the decorated function to be recorded in
167
+ the given DebugChannel's output. If you put that into a file named foo.py and
168
+ then run "python3 -m foo", you'll get this:
169
169
 
170
170
  ```
171
171
  DC: __main__: example2('First test',3) ...
@@ -189,6 +189,55 @@ DC: example2: example1(...) returns None after 23µs.
189
189
  DC: __main__: example2(...) returns None after 423ms.
190
190
  ```
191
191
 
192
+ When outputting a data structure, it's nice to be a little structured about it.
193
+ So if you send a list, tuple, dict, or set to a DebugChannel instance as the
194
+ whole message, it will be formatted one item at a time in the output.
195
+
196
+ ```python
197
+ from debug import DebugChannel
198
+
199
+ dc=DebugChannel(True,fmt="{label}: {line:3}: {indent}{message}\n")
200
+
201
+ l="this is a test".split()
202
+ s=set(l)
203
+ d=dict(zip('abcd',l))
204
+
205
+ dc("l:")(l)
206
+ dc("s:")(s)
207
+ dc("d:")(d)
208
+ ```
209
+
210
+ Notice the idiom of using dc(...)'s output as the DebugChannel instance itself,
211
+ allowing further manipulation in the same "breath." Here's the output:
212
+
213
+ ```python
214
+ DC: 12: l:
215
+ DC: 12: [
216
+ DC: 12: 'this',
217
+ DC: 12: 'is',
218
+ DC: 12: 'a',
219
+ DC: 12: 'test'
220
+ DC: 12: ]
221
+ DC: 13: s:
222
+ DC: 13: {
223
+ DC: 13: 'a',
224
+ DC: 13: 'is',
225
+ DC: 13: 'test',
226
+ DC: 13: 'this'
227
+ DC: 13: }
228
+ DC: 14: d:
229
+ DC: 14: {
230
+ DC: 14: 'a': 'this',
231
+ DC: 14: 'b': 'is',
232
+ DC: 14: 'c': 'a',
233
+ DC: 14: 'd': 'test'
234
+ DC: 14: }
235
+ ```
236
+
237
+ Notice sets are output in alphabetical order (according to their repr()
238
+ values). Since sets are unordered by nature, this makes them easier to inspect
239
+ visually without misrepresenting their contents.
240
+
192
241
  That's a very general start. See DebugChannel's class docs for more.
193
242
 
194
243
  <a id="debug.DebugChannel"></a>
@@ -2,8 +2,8 @@
2
2
 
3
3
  # debug
4
4
 
5
- This debug module a class named DebugChannel, instances of which are
6
- useful for adding temporary or conditional debug output to CLI scripts.
5
+ This debug module a class named DebugChannel, instances of which are useful for
6
+ adding temporary or conditional debug output to CLI scripts.
7
7
 
8
8
  The minimal boilerplate is pretty simple:
9
9
 
@@ -13,9 +13,9 @@ from debug import DebugChannel
13
13
  dc=DebugChannel(True)
14
14
  ```
15
15
 
16
- By default, DebugChannels are created disabled (the write no output), so
17
- the `True` above enables `dc` during its instantiation so it needn't be
18
- enabled later.
16
+ By default, DebugChannels are created disabled (the write no output), so the
17
+ `True` above enables `dc` during its instantiation so it needn't be enabled
18
+ later.
19
19
 
20
20
  A more common way of handling this is ...
21
21
 
@@ -33,18 +33,18 @@ dc.enable(opt.debug)
33
33
  ...
34
34
  ```
35
35
 
36
- This enables the `dc` DebugChannel instance only if --debug is given on
37
- the script's command line.
36
+ This enables the `dc` DebugChannel instance only if --debug is given on the
37
+ script's command line.
38
38
 
39
39
  By default, output is sent to stdandard error and formatted as:
40
40
 
41
41
  '{label}: [{pid}] {basename}:{line}:{function}: {indent}{message}\n'
42
42
 
43
- There are several variables you can include in DebugChannel's output.
44
- See the DebugChannel docs below for a list.
43
+ There are several variables you can include in DebugChannel's output. See the
44
+ DebugChannel docs below for a list.
45
45
 
46
- So, for example, if you want to see how your variables are behaving in a
47
- loop, you might do something like this:
46
+ So, for example, if you want to see how your variables are behaving in a loop,
47
+ you might do something like this:
48
48
 
49
49
  ```python
50
50
  from debug import DebugChannel
@@ -56,15 +56,15 @@ dc=DebugChannel(
56
56
 
57
57
  dc("Entering loop ...").indent()
58
58
  for i in range(5):
59
- dc(f"i={i}").indent()
59
+ dc(f"{i=}").indent()
60
60
  for j in range(3):
61
- dc(f"j={j}")
61
+ dc(f"{j=}")
62
62
  dc.undent()("Done with j loop.")
63
63
  dc.undent()("Done with i loop.")
64
64
  ```
65
65
 
66
- That gives you this necely indented output. The indent() and undent()
67
- methods are one thing that makes DebugChannels so nice to work with.
66
+ That gives you this necely indented output. The indent() and undent() methods
67
+ are one thing that makes DebugChannels so nice to work with.
68
68
 
69
69
  DC: 8: Entering loop ...
70
70
  DC: 10: i=0
@@ -94,8 +94,8 @@ methods are one thing that makes DebugChannels so nice to work with.
94
94
  DC: 13: Done with j loop.
95
95
  DC: 14: Done with i loop.
96
96
 
97
- That's a simple example, but you might be starting to get an idea of
98
- how versatile DebugChannel instances can be.
97
+ That's a simple example, but you might be starting to get an idea of how
98
+ versatile DebugChannel instances can be.
99
99
 
100
100
  A DebugChannel can also be used as a function decorator:
101
101
 
@@ -123,9 +123,9 @@ example2("First test",3)
123
123
  example2("Second test",2)
124
124
  ```
125
125
 
126
- This causes entry into and exit from the decorated function to be
127
- recorded in the given DebugChannel's output. If you put that into a file
128
- named foo.py and then run "python3 -m foo", you'll get this:
126
+ This causes entry into and exit from the decorated function to be recorded in
127
+ the given DebugChannel's output. If you put that into a file named foo.py and
128
+ then run "python3 -m foo", you'll get this:
129
129
 
130
130
  ```
131
131
  DC: __main__: example2('First test',3) ...
@@ -149,6 +149,55 @@ DC: example2: example1(...) returns None after 23µs.
149
149
  DC: __main__: example2(...) returns None after 423ms.
150
150
  ```
151
151
 
152
+ When outputting a data structure, it's nice to be a little structured about it.
153
+ So if you send a list, tuple, dict, or set to a DebugChannel instance as the
154
+ whole message, it will be formatted one item at a time in the output.
155
+
156
+ ```python
157
+ from debug import DebugChannel
158
+
159
+ dc=DebugChannel(True,fmt="{label}: {line:3}: {indent}{message}\n")
160
+
161
+ l="this is a test".split()
162
+ s=set(l)
163
+ d=dict(zip('abcd',l))
164
+
165
+ dc("l:")(l)
166
+ dc("s:")(s)
167
+ dc("d:")(d)
168
+ ```
169
+
170
+ Notice the idiom of using dc(...)'s output as the DebugChannel instance itself,
171
+ allowing further manipulation in the same "breath." Here's the output:
172
+
173
+ ```python
174
+ DC: 12: l:
175
+ DC: 12: [
176
+ DC: 12: 'this',
177
+ DC: 12: 'is',
178
+ DC: 12: 'a',
179
+ DC: 12: 'test'
180
+ DC: 12: ]
181
+ DC: 13: s:
182
+ DC: 13: {
183
+ DC: 13: 'a',
184
+ DC: 13: 'is',
185
+ DC: 13: 'test',
186
+ DC: 13: 'this'
187
+ DC: 13: }
188
+ DC: 14: d:
189
+ DC: 14: {
190
+ DC: 14: 'a': 'this',
191
+ DC: 14: 'b': 'is',
192
+ DC: 14: 'c': 'a',
193
+ DC: 14: 'd': 'test'
194
+ DC: 14: }
195
+ ```
196
+
197
+ Notice sets are output in alphabetical order (according to their repr()
198
+ values). Since sets are unordered by nature, this makes them easier to inspect
199
+ visually without misrepresenting their contents.
200
+
152
201
  That's a very general start. See DebugChannel's class docs for more.
153
202
 
154
203
  <a id="debug.DebugChannel"></a>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jc-debug"
7
- version = "1.0.2" # Consider using a proper versioning scheme
7
+ version = "1.0.3" # Consider using a proper versioning scheme
8
8
  authors = [
9
9
  { name="Jeff Clough", email="jeff@cloughcottage.com" },
10
10
  ]
@@ -155,7 +155,7 @@ __all__ = [
155
155
  "DebugChannel",
156
156
  "line_iter",
157
157
  ]
158
- __version__ = "1.0.2"
158
+ __version__ = "1.0.3"
159
159
 
160
160
  import inspect, os, sys, traceback
161
161
 
@@ -547,16 +547,23 @@ class DebugChannel:
547
547
  return self # Return without writing any output.
548
548
 
549
549
  # Format our message and write it to the debug stream.
550
- if isinstance(message, (list, tuple)):
550
+ sort=False
551
+ if isinstance(message, (list, set, tuple)):
551
552
  if isinstance(message, tuple):
552
553
  left, right = "()"
554
+ elif isinstance(message, set):
555
+ left, right = "{}"
556
+ message=sorted(list(message),key=lambda val:repr(val))
553
557
  else:
554
558
  left, right = "[]"
555
559
  messages = message
556
560
  message = left
557
561
  self.stream.write(self.fmt.format(**locals()))
558
- for message in messages:
559
- message = self.indstr + repr(message)
562
+ for i in range(len(messages)):
563
+ m = messages[i]
564
+ message = f"{self.indstr}{m!r}"
565
+ if i<len(messages)-1:
566
+ message+=','
560
567
  self.stream.write(self.fmt.format(**locals()))
561
568
  message = right
562
569
  self.stream.write(self.fmt.format(**locals()))
@@ -564,8 +571,10 @@ class DebugChannel:
564
571
  messages = dict(message)
565
572
  message = "{"
566
573
  self.stream.write(self.fmt.format(**locals()))
567
- for k in messages.keys():
568
- message = f"{self.indstr}{k!r}: {messages[k]!r}"
574
+ for i,(k,v) in enumerate(messages.items()):
575
+ message = f"{self.indstr}{k!r}: {v!r}"
576
+ if i<len(messages)-1:
577
+ message+=','
569
578
  self.stream.write(self.fmt.format(**locals()))
570
579
  message = "}"
571
580
  self.stream.write(self.fmt.format(**locals()))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jc-debug
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: Makes debugging to the console both simpler and much more powerful.
5
5
  Author-email: Jeff Clough <jeff@cloughcottage.com>
6
6
  License: MIT License
@@ -42,8 +42,8 @@ Dynamic: license-file
42
42
 
43
43
  # debug
44
44
 
45
- This debug module a class named DebugChannel, instances of which are
46
- useful for adding temporary or conditional debug output to CLI scripts.
45
+ This debug module a class named DebugChannel, instances of which are useful for
46
+ adding temporary or conditional debug output to CLI scripts.
47
47
 
48
48
  The minimal boilerplate is pretty simple:
49
49
 
@@ -53,9 +53,9 @@ from debug import DebugChannel
53
53
  dc=DebugChannel(True)
54
54
  ```
55
55
 
56
- By default, DebugChannels are created disabled (the write no output), so
57
- the `True` above enables `dc` during its instantiation so it needn't be
58
- enabled later.
56
+ By default, DebugChannels are created disabled (the write no output), so the
57
+ `True` above enables `dc` during its instantiation so it needn't be enabled
58
+ later.
59
59
 
60
60
  A more common way of handling this is ...
61
61
 
@@ -73,18 +73,18 @@ dc.enable(opt.debug)
73
73
  ...
74
74
  ```
75
75
 
76
- This enables the `dc` DebugChannel instance only if --debug is given on
77
- the script's command line.
76
+ This enables the `dc` DebugChannel instance only if --debug is given on the
77
+ script's command line.
78
78
 
79
79
  By default, output is sent to stdandard error and formatted as:
80
80
 
81
81
  '{label}: [{pid}] {basename}:{line}:{function}: {indent}{message}\n'
82
82
 
83
- There are several variables you can include in DebugChannel's output.
84
- See the DebugChannel docs below for a list.
83
+ There are several variables you can include in DebugChannel's output. See the
84
+ DebugChannel docs below for a list.
85
85
 
86
- So, for example, if you want to see how your variables are behaving in a
87
- loop, you might do something like this:
86
+ So, for example, if you want to see how your variables are behaving in a loop,
87
+ you might do something like this:
88
88
 
89
89
  ```python
90
90
  from debug import DebugChannel
@@ -96,15 +96,15 @@ dc=DebugChannel(
96
96
 
97
97
  dc("Entering loop ...").indent()
98
98
  for i in range(5):
99
- dc(f"i={i}").indent()
99
+ dc(f"{i=}").indent()
100
100
  for j in range(3):
101
- dc(f"j={j}")
101
+ dc(f"{j=}")
102
102
  dc.undent()("Done with j loop.")
103
103
  dc.undent()("Done with i loop.")
104
104
  ```
105
105
 
106
- That gives you this necely indented output. The indent() and undent()
107
- methods are one thing that makes DebugChannels so nice to work with.
106
+ That gives you this necely indented output. The indent() and undent() methods
107
+ are one thing that makes DebugChannels so nice to work with.
108
108
 
109
109
  DC: 8: Entering loop ...
110
110
  DC: 10: i=0
@@ -134,8 +134,8 @@ methods are one thing that makes DebugChannels so nice to work with.
134
134
  DC: 13: Done with j loop.
135
135
  DC: 14: Done with i loop.
136
136
 
137
- That's a simple example, but you might be starting to get an idea of
138
- how versatile DebugChannel instances can be.
137
+ That's a simple example, but you might be starting to get an idea of how
138
+ versatile DebugChannel instances can be.
139
139
 
140
140
  A DebugChannel can also be used as a function decorator:
141
141
 
@@ -163,9 +163,9 @@ example2("First test",3)
163
163
  example2("Second test",2)
164
164
  ```
165
165
 
166
- This causes entry into and exit from the decorated function to be
167
- recorded in the given DebugChannel's output. If you put that into a file
168
- named foo.py and then run "python3 -m foo", you'll get this:
166
+ This causes entry into and exit from the decorated function to be recorded in
167
+ the given DebugChannel's output. If you put that into a file named foo.py and
168
+ then run "python3 -m foo", you'll get this:
169
169
 
170
170
  ```
171
171
  DC: __main__: example2('First test',3) ...
@@ -189,6 +189,55 @@ DC: example2: example1(...) returns None after 23µs.
189
189
  DC: __main__: example2(...) returns None after 423ms.
190
190
  ```
191
191
 
192
+ When outputting a data structure, it's nice to be a little structured about it.
193
+ So if you send a list, tuple, dict, or set to a DebugChannel instance as the
194
+ whole message, it will be formatted one item at a time in the output.
195
+
196
+ ```python
197
+ from debug import DebugChannel
198
+
199
+ dc=DebugChannel(True,fmt="{label}: {line:3}: {indent}{message}\n")
200
+
201
+ l="this is a test".split()
202
+ s=set(l)
203
+ d=dict(zip('abcd',l))
204
+
205
+ dc("l:")(l)
206
+ dc("s:")(s)
207
+ dc("d:")(d)
208
+ ```
209
+
210
+ Notice the idiom of using dc(...)'s output as the DebugChannel instance itself,
211
+ allowing further manipulation in the same "breath." Here's the output:
212
+
213
+ ```python
214
+ DC: 12: l:
215
+ DC: 12: [
216
+ DC: 12: 'this',
217
+ DC: 12: 'is',
218
+ DC: 12: 'a',
219
+ DC: 12: 'test'
220
+ DC: 12: ]
221
+ DC: 13: s:
222
+ DC: 13: {
223
+ DC: 13: 'a',
224
+ DC: 13: 'is',
225
+ DC: 13: 'test',
226
+ DC: 13: 'this'
227
+ DC: 13: }
228
+ DC: 14: d:
229
+ DC: 14: {
230
+ DC: 14: 'a': 'this',
231
+ DC: 14: 'b': 'is',
232
+ DC: 14: 'c': 'a',
233
+ DC: 14: 'd': 'test'
234
+ DC: 14: }
235
+ ```
236
+
237
+ Notice sets are output in alphabetical order (according to their repr()
238
+ values). Since sets are unordered by nature, this makes them easier to inspect
239
+ visually without misrepresenting their contents.
240
+
192
241
  That's a very general start. See DebugChannel's class docs for more.
193
242
 
194
243
  <a id="debug.DebugChannel"></a>
@@ -92,8 +92,8 @@ DC: test_basics: Message 2
92
92
  dc(('a',2,True))
93
93
  assert outstr()=="""\
94
94
  DC: test_basics: (
95
- DC: test_basics: 'a'
96
- DC: test_basics: 2
95
+ DC: test_basics: 'a',
96
+ DC: test_basics: 2,
97
97
  DC: test_basics: True
98
98
  DC: test_basics: )
99
99
  """
@@ -102,18 +102,28 @@ DC: test_basics: )
102
102
  dc(['a',2,True])
103
103
  assert outstr()=="""\
104
104
  DC: test_basics: [
105
- DC: test_basics: 'a'
106
- DC: test_basics: 2
105
+ DC: test_basics: 'a',
106
+ DC: test_basics: 2,
107
107
  DC: test_basics: True
108
108
  DC: test_basics: ]
109
+ """
110
+
111
+ # Test set output.
112
+ dc(set(['a',2,True]))
113
+ assert outstr()=="""\
114
+ DC: test_basics: {
115
+ DC: test_basics: 'a',
116
+ DC: test_basics: 2,
117
+ DC: test_basics: True
118
+ DC: test_basics: }
109
119
  """
110
120
 
111
121
  # Test dictionary output.
112
122
  dc({'a':1,2:'b','c':True})
113
123
  assert outstr()=="""\
114
124
  DC: test_basics: {
115
- DC: test_basics: 'a': 1
116
- DC: test_basics: 2: 'b'
125
+ DC: test_basics: 'a': 1,
126
+ DC: test_basics: 2: 'b',
117
127
  DC: test_basics: 'c': True
118
128
  DC: test_basics: }
119
129
  """
File without changes
File without changes