peek-python 24.0.2.post2__tar.gz → 24.0.4__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.1
2
2
  Name: peek-python
3
- Version: 24.0.2.post2
3
+ Version: 24.0.4
4
4
  Summary: peek - debugging and benchmarking made easy
5
5
  Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/salabim/peek
@@ -44,6 +44,8 @@ And on top of that, you get some basic benchmarking functionality.
44
44
 
45
45
  * [Configuration](#configuration)
46
46
 
47
+ * [Use peek.print to mimic print with extras](#use-peek.print-to-mimic-print-with-extras)
48
+
47
49
  * [Return a string instead of sending to output](#return-a-string-instead-of-sending-to-output)
48
50
 
49
51
  * [Disabling peek's output](#disabling-peeks-output)
@@ -325,7 +327,7 @@ context_separator cs " ==> "
325
327
  depth - 1000000
326
328
  delta - 0
327
329
  enabled - True
328
- enforce_line_length - False
330
+ end - "\n"
329
331
  equals_separator - "="
330
332
  filter f ""
331
333
  indent - 1
@@ -336,6 +338,7 @@ prefix pr ""
336
338
  quote_string qs True
337
339
  return_none - False
338
340
  separator sep ", "
341
+ separator_print sepp "" "
339
342
  serialize - pprint.pformat
340
343
  show_delta sd False
341
344
  show_enter se True
@@ -820,7 +823,7 @@ Note that under Python <=3.7, numbers are never underscored.
820
823
 
821
824
  ## seperator / sep
822
825
 
823
- By default, pairs (on one line) are separated by `, `.
826
+ By default, pairs (on one line) are separated by `", ""`.
824
827
  It is possible to change this with the attribute ` separator`:
825
828
 
826
829
  ```
@@ -833,8 +836,8 @@ peek(a, (b, c), d, separator=" | ")
833
836
  ```
834
837
  prints
835
838
  ```
836
- a='abcd', (b,c)=(1, 1000), d=['peek', 'c', 'e', 'c', 'r', 'e', 'a', 'm']
837
- a='abcd' | (b,c)=(1, 1000) | d=['peek', 'c', 'e', 'c', 'r', 'e', 'a', 'm']
839
+ a='abcd', (b,c)=(1, 1000), d=['p', 'e', 'e', 'k']
840
+ a='abcd' | (b,c)=(1, 1000) | d=['p', 'e', 'e', 'k']
838
841
  ```
839
842
 
840
843
  ## context_separator
@@ -898,8 +901,6 @@ prints
898
901
  hello='world', 2 * hello='worldworld'
899
902
  'world', 'worldworld'
900
903
  ```
901
- The values=True version of peek can be seen as a supercharged print/pprint.
902
-
903
904
 
904
905
  ## values_only_for_fstrings / voff
905
906
  If False (the default), both the original f-string and the
@@ -920,6 +921,29 @@ x=1.230e+01
920
921
  ```
921
922
  Note that if `values_only` is True, f-string will be suppressed, regardless of `values_only_for_fstrings`.
922
923
 
924
+ ## end
925
+ The `end` attribute works like the end parameter of print. By default, `end` is "\n".
926
+ This can be useful to have several peek outputs on one line, like:
927
+
928
+ ```
929
+ for i in range(5):
930
+ peek(i*i, end=' ')
931
+ peek('')
932
+ ```
933
+ Maybe more useful is to show the output change on the same line, e.g. a status.
934
+ ```
935
+ import time
936
+ for i in range(50):
937
+ peek(f"time {time.time()}",end="\r")
938
+ time.sleep(0.1)
939
+ peek('')
940
+ ```
941
+ The `end` parameter will be only applied when output is stdout, stdout_nocolor or stderr.
942
+
943
+ > [!NOTE]
944
+ >
945
+ > `\r` does not work under Pythonista.
946
+
923
947
  ## return_none
924
948
  Normally, `peek()`returns the values passed directly, which is usually fine. However, when used in a notebook
925
949
  or REPL, that value will be shown, and that can be annoying. Therefore, if `return_none`is True, `peek()`will
@@ -940,9 +964,6 @@ a=3, b=4
940
964
  None
941
965
  ```
942
966
 
943
- ## enforce_line_length
944
- If enforce_line_length is True, all output lines are explicitly truncated to the given line_length, even those that are not truncated by pformat.
945
-
946
967
  ## delta
947
968
  The delta attribute can be used to (re)set the current delta, e.g.
948
969
  ```
@@ -951,6 +972,58 @@ print(peek.delta)
951
972
  ```
952
973
  prints a value that id slightly more than 0.
953
974
 
975
+ # Use peek.print to mimic print with extras
976
+ The method `peek.print` allows peek to be used as alternative to print. Note that `peek.print` obeys the `color`, `enabled`, `filter` and `output`. It is also possible to redirect the output to as stringg with `as_str`.
977
+
978
+ So,
979
+
980
+ ```
981
+ peek.color = "red"
982
+ peek.filter = "level==1"
983
+ peek.print(f"{max(1, 2)=}") # default level is 0, so this will be suppressed
984
+ peek.print(f"{min(1, 2)=}", level=1)
985
+ ```
986
+
987
+ will print
988
+
989
+ ```
990
+ min(1, 2)=1
991
+ ```
992
+
993
+ in red.
994
+
995
+ The `peek.print`() method applies the prefix and end attributes to the ouput.
996
+
997
+ In order to behave similar to print, `peek` has an extra attribute, `separator_print` (alias: `sepp`). This attribute (default " ") will be used when `peek.printing`.
998
+ When calling `peek.print`, `sep` may be used instead. So
999
+
1000
+ ```
1001
+ peek.sepp = "|"
1002
+ peek.print("test")
1003
+ ```
1004
+
1005
+ Has the same effect as
1006
+
1007
+ ```
1008
+ peek.print("test", sep="|")
1009
+ ```
1010
+
1011
+ and
1012
+
1013
+ ```
1014
+ peek.print("test", sepp="|")
1015
+ ```
1016
+
1017
+ but not the same as
1018
+
1019
+ ```
1020
+ peek.sep = "|" # sets the 'normal' peek separator
1021
+ ```
1022
+
1023
+ > [!NOTE]
1024
+ >
1025
+ > The value of the attributes `color_value`, `compact`, `context_separator`, `depth`, `delta`, `equals_separator`, `indent`, `line_length`, `quote_string`, `return_none`, `serialize`, `show_delta`, `show_enter`, `show_exit`, `show_time`, `show_traceback`, `sort_dicts`, `to_clipboard`, `underscore_numbers`, `values_only`, `values_only_for_fstrings` are ignored when using `peek.print`.
1026
+
954
1027
  # Return a string instead of sending to output
955
1028
 
956
1029
  `peek(*args, as_str=True)` is like `peek(*args)` but the output is returned as a string instead
@@ -1273,6 +1346,8 @@ usable without installation yes no
1273
1346
  can be used as a decorator yes no
1274
1347
  can be used as a context manager yes no
1275
1348
  can show traceback yes no
1349
+ mimics print() with extras yes (peek.print()) no
1350
+ allows non linefeed printing yes (via end parameter) requires patching
1276
1351
  PEP8 (Pythonic) API yes no
1277
1352
  sorts dicts no by default, optional *) yes
1278
1353
  supports compact, indent,
@@ -24,6 +24,8 @@ And on top of that, you get some basic benchmarking functionality.
24
24
 
25
25
  * [Configuration](#configuration)
26
26
 
27
+ * [Use peek.print to mimic print with extras](#use-peek.print-to-mimic-print-with-extras)
28
+
27
29
  * [Return a string instead of sending to output](#return-a-string-instead-of-sending-to-output)
28
30
 
29
31
  * [Disabling peek's output](#disabling-peeks-output)
@@ -305,7 +307,7 @@ context_separator cs " ==> "
305
307
  depth - 1000000
306
308
  delta - 0
307
309
  enabled - True
308
- enforce_line_length - False
310
+ end - "\n"
309
311
  equals_separator - "="
310
312
  filter f ""
311
313
  indent - 1
@@ -316,6 +318,7 @@ prefix pr ""
316
318
  quote_string qs True
317
319
  return_none - False
318
320
  separator sep ", "
321
+ separator_print sepp "" "
319
322
  serialize - pprint.pformat
320
323
  show_delta sd False
321
324
  show_enter se True
@@ -800,7 +803,7 @@ Note that under Python <=3.7, numbers are never underscored.
800
803
 
801
804
  ## seperator / sep
802
805
 
803
- By default, pairs (on one line) are separated by `, `.
806
+ By default, pairs (on one line) are separated by `", ""`.
804
807
  It is possible to change this with the attribute ` separator`:
805
808
 
806
809
  ```
@@ -813,8 +816,8 @@ peek(a, (b, c), d, separator=" | ")
813
816
  ```
814
817
  prints
815
818
  ```
816
- a='abcd', (b,c)=(1, 1000), d=['peek', 'c', 'e', 'c', 'r', 'e', 'a', 'm']
817
- a='abcd' | (b,c)=(1, 1000) | d=['peek', 'c', 'e', 'c', 'r', 'e', 'a', 'm']
819
+ a='abcd', (b,c)=(1, 1000), d=['p', 'e', 'e', 'k']
820
+ a='abcd' | (b,c)=(1, 1000) | d=['p', 'e', 'e', 'k']
818
821
  ```
819
822
 
820
823
  ## context_separator
@@ -878,8 +881,6 @@ prints
878
881
  hello='world', 2 * hello='worldworld'
879
882
  'world', 'worldworld'
880
883
  ```
881
- The values=True version of peek can be seen as a supercharged print/pprint.
882
-
883
884
 
884
885
  ## values_only_for_fstrings / voff
885
886
  If False (the default), both the original f-string and the
@@ -900,6 +901,29 @@ x=1.230e+01
900
901
  ```
901
902
  Note that if `values_only` is True, f-string will be suppressed, regardless of `values_only_for_fstrings`.
902
903
 
904
+ ## end
905
+ The `end` attribute works like the end parameter of print. By default, `end` is "\n".
906
+ This can be useful to have several peek outputs on one line, like:
907
+
908
+ ```
909
+ for i in range(5):
910
+ peek(i*i, end=' ')
911
+ peek('')
912
+ ```
913
+ Maybe more useful is to show the output change on the same line, e.g. a status.
914
+ ```
915
+ import time
916
+ for i in range(50):
917
+ peek(f"time {time.time()}",end="\r")
918
+ time.sleep(0.1)
919
+ peek('')
920
+ ```
921
+ The `end` parameter will be only applied when output is stdout, stdout_nocolor or stderr.
922
+
923
+ > [!NOTE]
924
+ >
925
+ > `\r` does not work under Pythonista.
926
+
903
927
  ## return_none
904
928
  Normally, `peek()`returns the values passed directly, which is usually fine. However, when used in a notebook
905
929
  or REPL, that value will be shown, and that can be annoying. Therefore, if `return_none`is True, `peek()`will
@@ -920,9 +944,6 @@ a=3, b=4
920
944
  None
921
945
  ```
922
946
 
923
- ## enforce_line_length
924
- If enforce_line_length is True, all output lines are explicitly truncated to the given line_length, even those that are not truncated by pformat.
925
-
926
947
  ## delta
927
948
  The delta attribute can be used to (re)set the current delta, e.g.
928
949
  ```
@@ -931,6 +952,58 @@ print(peek.delta)
931
952
  ```
932
953
  prints a value that id slightly more than 0.
933
954
 
955
+ # Use peek.print to mimic print with extras
956
+ The method `peek.print` allows peek to be used as alternative to print. Note that `peek.print` obeys the `color`, `enabled`, `filter` and `output`. It is also possible to redirect the output to as stringg with `as_str`.
957
+
958
+ So,
959
+
960
+ ```
961
+ peek.color = "red"
962
+ peek.filter = "level==1"
963
+ peek.print(f"{max(1, 2)=}") # default level is 0, so this will be suppressed
964
+ peek.print(f"{min(1, 2)=}", level=1)
965
+ ```
966
+
967
+ will print
968
+
969
+ ```
970
+ min(1, 2)=1
971
+ ```
972
+
973
+ in red.
974
+
975
+ The `peek.print`() method applies the prefix and end attributes to the ouput.
976
+
977
+ In order to behave similar to print, `peek` has an extra attribute, `separator_print` (alias: `sepp`). This attribute (default " ") will be used when `peek.printing`.
978
+ When calling `peek.print`, `sep` may be used instead. So
979
+
980
+ ```
981
+ peek.sepp = "|"
982
+ peek.print("test")
983
+ ```
984
+
985
+ Has the same effect as
986
+
987
+ ```
988
+ peek.print("test", sep="|")
989
+ ```
990
+
991
+ and
992
+
993
+ ```
994
+ peek.print("test", sepp="|")
995
+ ```
996
+
997
+ but not the same as
998
+
999
+ ```
1000
+ peek.sep = "|" # sets the 'normal' peek separator
1001
+ ```
1002
+
1003
+ > [!NOTE]
1004
+ >
1005
+ > The value of the attributes `color_value`, `compact`, `context_separator`, `depth`, `delta`, `equals_separator`, `indent`, `line_length`, `quote_string`, `return_none`, `serialize`, `show_delta`, `show_enter`, `show_exit`, `show_time`, `show_traceback`, `sort_dicts`, `to_clipboard`, `underscore_numbers`, `values_only`, `values_only_for_fstrings` are ignored when using `peek.print`.
1006
+
934
1007
  # Return a string instead of sending to output
935
1008
 
936
1009
  `peek(*args, as_str=True)` is like `peek(*args)` but the output is returned as a string instead
@@ -1253,6 +1326,8 @@ usable without installation yes no
1253
1326
  can be used as a decorator yes no
1254
1327
  can be used as a context manager yes no
1255
1328
  can show traceback yes no
1329
+ mimics print() with extras yes (peek.print()) no
1330
+ allows non linefeed printing yes (via end parameter) requires patching
1256
1331
  PEP8 (Pythonic) API yes no
1257
1332
  sorts dicts no by default, optional *) yes
1258
1333
  supports compact, indent,
@@ -4,7 +4,7 @@
4
4
  # | .__/ \___| \___||_|\_\
5
5
  # |_| like print, but easy.
6
6
 
7
- __version__ = "24.0.2"
7
+ __version__ = "24.0.4"
8
8
 
9
9
  """
10
10
  See https://github.com/salabim/peek for details
@@ -56,6 +56,7 @@ def perf_counter():
56
56
  return time.perf_counter() if _fixed_perf_counter is None else _fixed_perf_counter
57
57
 
58
58
 
59
+ codes = {}
59
60
  colors = dict(
60
61
  black="\033[0;30m",
61
62
  red="\033[0;31m",
@@ -67,6 +68,7 @@ colors = dict(
67
68
  white="\033[0;37m",
68
69
  )
69
70
  colors["-"] = "\033[0m"
71
+ colors[""] = "\033[0m"
70
72
 
71
73
 
72
74
  ansi_to_rgb = {
@@ -111,8 +113,6 @@ def check_validity(name, value):
111
113
  return
112
114
 
113
115
  if name in ("color", "color_value"):
114
- if name == "color_value" and value == "":
115
- return
116
116
  if isinstance(value, str) and value.lower() in colors:
117
117
  return
118
118
 
@@ -120,13 +120,6 @@ def check_validity(name, value):
120
120
  if isinstance(value, numbers.Number):
121
121
  return
122
122
 
123
- elif name == "enforce_line_length":
124
- if value:
125
- if isinstance(value, numbers.Number) and value > 0:
126
- return
127
- else:
128
- return
129
-
130
123
  elif name == "line_length":
131
124
  if isinstance(value, numbers.Number) and value > 0:
132
125
  return
@@ -164,9 +157,11 @@ def check_validity(name, value):
164
157
  _fixed_perf_counter = None
165
158
 
166
159
 
167
- def spec_to_attributes(d):
160
+ def spec_to_attributes(**kwargs):
168
161
  result = {}
169
- for name, value in d.items():
162
+ for name, value in kwargs.items():
163
+ if alias_name.get(name, "") in kwargs:
164
+ raise AttributeError(f"not allowed to use {name} and {alias_name.get(name)} both.")
170
165
  check_validity(name, value)
171
166
  name = de_alias(name)
172
167
  if name == "delta" and value is not None:
@@ -188,6 +183,19 @@ def read_toml():
188
183
  return {}
189
184
 
190
185
 
186
+ def print_pythonista_color(s, end="\n"):
187
+ while s:
188
+ for ansi, rgb in ansi_to_rgb.items():
189
+ if s.startswith(ansi):
190
+ console.set_color(*rgb)
191
+ s = s[len(ansi) :]
192
+ break
193
+ else:
194
+ print(s[0], end="")
195
+ s = s[1:]
196
+ print("", end=end)
197
+
198
+
191
199
  def no_source_error():
192
200
  raise NotImplementedError(
193
201
  """
@@ -210,7 +218,7 @@ def return_args(args, return_none):
210
218
 
211
219
  class _Peek:
212
220
  def __init__(self, parent=None, **kwargs):
213
- self._attributes = spec_to_attributes(kwargs)
221
+ self._attributes = spec_to_attributes(**kwargs)
214
222
  self._parent = parent
215
223
 
216
224
  def new(self, ignore_toml=False, **kwargs):
@@ -224,11 +232,11 @@ class _Peek:
224
232
 
225
233
  def clone(self, **kwargs):
226
234
  clone = _Peek(parent=self._parent)
227
- clone._attributes = {**self._attributes, **spec_to_attributes(kwargs)}
235
+ clone._attributes = {**self._attributes, **spec_to_attributes(**kwargs)}
228
236
  return clone
229
237
 
230
238
  def configure(self, **kwargs):
231
- self._attributes.update(spec_to_attributes(kwargs))
239
+ self._attributes.update(spec_to_attributes(**kwargs))
232
240
 
233
241
  def __getattr__(self, item, spec=False):
234
242
  item = de_alias(item)
@@ -240,6 +248,9 @@ class _Peek:
240
248
  return perf_counter() - node._attributes["perf_counter"] + node._attributes["delta"]
241
249
  elif item == "perf_counter":
242
250
  return node._attributes["delta"]
251
+ elif item == "prefix":
252
+ prefix = node._attributes[item]
253
+ return str(prefix() if callable(prefix) else prefix)
243
254
  else:
244
255
  return node._attributes[item]
245
256
  else:
@@ -248,7 +259,7 @@ class _Peek:
248
259
  def __setattr__(self, item, value):
249
260
  if item in ("_parent", "_is_context_manager", "_line_number_with_filename_and_parent", "_save_traceback", "_enter_time", "_as_str", "_attributes"):
250
261
  return super().__setattr__(item, value)
251
- self._attributes.update(spec_to_attributes({item: value}))
262
+ self._attributes.update(spec_to_attributes(**{item: value}))
252
263
 
253
264
  def __repr__(self):
254
265
  pairs = [
@@ -272,8 +283,31 @@ class _Peek:
272
283
  return False
273
284
  return self.enabled
274
285
 
286
+ def print(self, *args, as_str=False, **kwargs):
287
+ diff = {"sep", "separator", "sepp", "separator_print"} & set(kwargs)
288
+ if len(diff) >= 2:
289
+ raise AttributeError(f"multiple keyword for separator found: {diff}")
290
+ if "sep" in kwargs:
291
+ kwargs["separator_print"] = kwargs["sep"]
292
+ if "separator" in kwargs:
293
+ kwargs["separator_print"] = kwargs["separator"]
294
+
295
+ this = self.fork(**kwargs)
296
+
297
+ if not this.do_show():
298
+ if as_str:
299
+ return ""
300
+ else:
301
+ return return_args(args, this.return_none)
302
+
303
+ s = this.prefix + this.separator_print.join(map(str, args))
304
+
305
+ if as_str:
306
+ return s + this.end
307
+
308
+ this.do_output(s)
309
+
275
310
  def __call__(self, *args, as_str=False, **kwargs):
276
- codes = {}
277
311
  this = self.fork(**kwargs)
278
312
 
279
313
  this._as_str = as_str
@@ -500,9 +534,7 @@ class _Peek:
500
534
 
501
535
  if as_str:
502
536
  if this.do_show():
503
- if this.enforce_line_length:
504
- out = "\n".join(line[: this.line_length] for line in out.splitlines())
505
- return out + "\n"
537
+ return out + this.end
506
538
  else:
507
539
  return ""
508
540
  if this.to_clipboard:
@@ -549,7 +581,7 @@ class _Peek:
549
581
  if not omit_context_separator and context:
550
582
  context += self.context_separator
551
583
 
552
- return str(self.prefix() if callable(self.prefix) else self.prefix) + context
584
+ return self.prefix + context
553
585
 
554
586
  def add_color_value(self, s):
555
587
  if self.output != "stdout" or self._as_str:
@@ -560,33 +592,26 @@ class _Peek:
560
592
  return s
561
593
 
562
594
  def do_output(self, s):
563
- if self.enforce_line_length:
564
- s = "\n".join(line[: self.line_length] for line in s.splitlines())
565
595
  if self.do_show():
566
596
  if callable(self.output):
567
- self.output(s)
597
+ if self.output == builtins.print or "end" in inspect.signature(self.output).parameters:
598
+ # test for builtins.print is required as for Python <= 3.10, builtins.print has no signature
599
+ self.output(s, end=self.end)
600
+ else:
601
+ self.output(s + self.end)
568
602
  elif self.output == "stderr":
569
- print(s, file=sys.stderr)
603
+ print(s, file=sys.stderr, end=self.end)
570
604
  elif self.output == "stdout":
571
- if self.color != "-" or self.color_value != "-":
572
- s = colors[self.color.lower()] + s + colors["-"]
605
+ if self.color not in ["", "-"]:
606
+ s = colors[self.color.lower()] + s + self.end + colors["-"]
573
607
  if Pythonista:
574
- while s:
575
- for ansi, rgb in ansi_to_rgb.items():
576
- if s.startswith(ansi):
577
- console.set_color(*rgb)
578
- s = s[len(ansi) :]
579
- break
580
- else:
581
- print(s[0], end="")
582
- s = s[1:]
583
- print()
608
+ print_pythonista_color(s, end="")
584
609
  else:
585
- print(s)
610
+ print(s, end="")
586
611
  else:
587
- print(s)
612
+ print(s, end=self.end)
588
613
  elif self.output == "stdout_nocolor":
589
- print(s)
614
+ print(s, end=self.end)
590
615
  elif self.output == "logging.debug":
591
616
  logging.debug(s)
592
617
  elif self.output == "logging.info":
@@ -601,12 +626,12 @@ class _Peek:
601
626
  pass
602
627
  elif isinstance(self.output, str):
603
628
  with open(self.output, "a+", encoding="utf-8") as f:
604
- print(s, file=f)
629
+ print(s, file=f, end=self.end)
605
630
  elif isinstance(self.output, Path):
606
631
  with self.output.open("a+", encoding="utf-8") as f:
607
- print(s, file=f)
632
+ print(s, file=f, end=self.end)
608
633
  else:
609
- print(s, file=self.output)
634
+ print(s, file=self.output, end=self.end)
610
635
 
611
636
  def copy_to_clipboard(self, value, confirm=True):
612
637
  if Pythonista:
@@ -656,7 +681,7 @@ name_alias_default = (
656
681
  ("delta", "", 0),
657
682
  ("depth", "", 1000000),
658
683
  ("enabled", "", True),
659
- ("enforce_line_length", "", False),
684
+ ("end", "", "\n"),
660
685
  ("equals_separator", "", "="),
661
686
  ("filter", "f", ""),
662
687
  ("indent", "", 1),
@@ -667,6 +692,7 @@ name_alias_default = (
667
692
  ("quote_string", "qs", True),
668
693
  ("return_none", "", False),
669
694
  ("separator", "sep", ", "),
695
+ ("separator_print", "sepp", " "),
670
696
  ("serialize", "", pprint.pformat),
671
697
  ("show_delta", "sd", False),
672
698
  ("show_enter", "se", True),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: peek-python
3
- Version: 24.0.2.post2
3
+ Version: 24.0.4
4
4
  Summary: peek - debugging and benchmarking made easy
5
5
  Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/salabim/peek
@@ -44,6 +44,8 @@ And on top of that, you get some basic benchmarking functionality.
44
44
 
45
45
  * [Configuration](#configuration)
46
46
 
47
+ * [Use peek.print to mimic print with extras](#use-peek.print-to-mimic-print-with-extras)
48
+
47
49
  * [Return a string instead of sending to output](#return-a-string-instead-of-sending-to-output)
48
50
 
49
51
  * [Disabling peek's output](#disabling-peeks-output)
@@ -325,7 +327,7 @@ context_separator cs " ==> "
325
327
  depth - 1000000
326
328
  delta - 0
327
329
  enabled - True
328
- enforce_line_length - False
330
+ end - "\n"
329
331
  equals_separator - "="
330
332
  filter f ""
331
333
  indent - 1
@@ -336,6 +338,7 @@ prefix pr ""
336
338
  quote_string qs True
337
339
  return_none - False
338
340
  separator sep ", "
341
+ separator_print sepp "" "
339
342
  serialize - pprint.pformat
340
343
  show_delta sd False
341
344
  show_enter se True
@@ -820,7 +823,7 @@ Note that under Python <=3.7, numbers are never underscored.
820
823
 
821
824
  ## seperator / sep
822
825
 
823
- By default, pairs (on one line) are separated by `, `.
826
+ By default, pairs (on one line) are separated by `", ""`.
824
827
  It is possible to change this with the attribute ` separator`:
825
828
 
826
829
  ```
@@ -833,8 +836,8 @@ peek(a, (b, c), d, separator=" | ")
833
836
  ```
834
837
  prints
835
838
  ```
836
- a='abcd', (b,c)=(1, 1000), d=['peek', 'c', 'e', 'c', 'r', 'e', 'a', 'm']
837
- a='abcd' | (b,c)=(1, 1000) | d=['peek', 'c', 'e', 'c', 'r', 'e', 'a', 'm']
839
+ a='abcd', (b,c)=(1, 1000), d=['p', 'e', 'e', 'k']
840
+ a='abcd' | (b,c)=(1, 1000) | d=['p', 'e', 'e', 'k']
838
841
  ```
839
842
 
840
843
  ## context_separator
@@ -898,8 +901,6 @@ prints
898
901
  hello='world', 2 * hello='worldworld'
899
902
  'world', 'worldworld'
900
903
  ```
901
- The values=True version of peek can be seen as a supercharged print/pprint.
902
-
903
904
 
904
905
  ## values_only_for_fstrings / voff
905
906
  If False (the default), both the original f-string and the
@@ -920,6 +921,29 @@ x=1.230e+01
920
921
  ```
921
922
  Note that if `values_only` is True, f-string will be suppressed, regardless of `values_only_for_fstrings`.
922
923
 
924
+ ## end
925
+ The `end` attribute works like the end parameter of print. By default, `end` is "\n".
926
+ This can be useful to have several peek outputs on one line, like:
927
+
928
+ ```
929
+ for i in range(5):
930
+ peek(i*i, end=' ')
931
+ peek('')
932
+ ```
933
+ Maybe more useful is to show the output change on the same line, e.g. a status.
934
+ ```
935
+ import time
936
+ for i in range(50):
937
+ peek(f"time {time.time()}",end="\r")
938
+ time.sleep(0.1)
939
+ peek('')
940
+ ```
941
+ The `end` parameter will be only applied when output is stdout, stdout_nocolor or stderr.
942
+
943
+ > [!NOTE]
944
+ >
945
+ > `\r` does not work under Pythonista.
946
+
923
947
  ## return_none
924
948
  Normally, `peek()`returns the values passed directly, which is usually fine. However, when used in a notebook
925
949
  or REPL, that value will be shown, and that can be annoying. Therefore, if `return_none`is True, `peek()`will
@@ -940,9 +964,6 @@ a=3, b=4
940
964
  None
941
965
  ```
942
966
 
943
- ## enforce_line_length
944
- If enforce_line_length is True, all output lines are explicitly truncated to the given line_length, even those that are not truncated by pformat.
945
-
946
967
  ## delta
947
968
  The delta attribute can be used to (re)set the current delta, e.g.
948
969
  ```
@@ -951,6 +972,58 @@ print(peek.delta)
951
972
  ```
952
973
  prints a value that id slightly more than 0.
953
974
 
975
+ # Use peek.print to mimic print with extras
976
+ The method `peek.print` allows peek to be used as alternative to print. Note that `peek.print` obeys the `color`, `enabled`, `filter` and `output`. It is also possible to redirect the output to as stringg with `as_str`.
977
+
978
+ So,
979
+
980
+ ```
981
+ peek.color = "red"
982
+ peek.filter = "level==1"
983
+ peek.print(f"{max(1, 2)=}") # default level is 0, so this will be suppressed
984
+ peek.print(f"{min(1, 2)=}", level=1)
985
+ ```
986
+
987
+ will print
988
+
989
+ ```
990
+ min(1, 2)=1
991
+ ```
992
+
993
+ in red.
994
+
995
+ The `peek.print`() method applies the prefix and end attributes to the ouput.
996
+
997
+ In order to behave similar to print, `peek` has an extra attribute, `separator_print` (alias: `sepp`). This attribute (default " ") will be used when `peek.printing`.
998
+ When calling `peek.print`, `sep` may be used instead. So
999
+
1000
+ ```
1001
+ peek.sepp = "|"
1002
+ peek.print("test")
1003
+ ```
1004
+
1005
+ Has the same effect as
1006
+
1007
+ ```
1008
+ peek.print("test", sep="|")
1009
+ ```
1010
+
1011
+ and
1012
+
1013
+ ```
1014
+ peek.print("test", sepp="|")
1015
+ ```
1016
+
1017
+ but not the same as
1018
+
1019
+ ```
1020
+ peek.sep = "|" # sets the 'normal' peek separator
1021
+ ```
1022
+
1023
+ > [!NOTE]
1024
+ >
1025
+ > The value of the attributes `color_value`, `compact`, `context_separator`, `depth`, `delta`, `equals_separator`, `indent`, `line_length`, `quote_string`, `return_none`, `serialize`, `show_delta`, `show_enter`, `show_exit`, `show_time`, `show_traceback`, `sort_dicts`, `to_clipboard`, `underscore_numbers`, `values_only`, `values_only_for_fstrings` are ignored when using `peek.print`.
1026
+
954
1027
  # Return a string instead of sending to output
955
1028
 
956
1029
  `peek(*args, as_str=True)` is like `peek(*args)` but the output is returned as a string instead
@@ -1273,6 +1346,8 @@ usable without installation yes no
1273
1346
  can be used as a decorator yes no
1274
1347
  can be used as a context manager yes no
1275
1348
  can show traceback yes no
1349
+ mimics print() with extras yes (peek.print()) no
1350
+ allows non linefeed printing yes (via end parameter) requires patching
1276
1351
  PEP8 (Pythonic) API yes no
1277
1352
  sorts dicts no by default, optional *) yes
1278
1353
  supports compact, indent,
@@ -10,7 +10,7 @@ authors = [
10
10
  { name = "Ruud van der Ham", email = "rt.van.der.ham@gmail.com" },
11
11
  ]
12
12
  description = "peek - debugging and benchmarking made easy"
13
- version = "24.0.2.post2"
13
+ version = "24.0.4"
14
14
  readme = "README.md"
15
15
  requires-python = ">=3.6"
16
16
  dependencies = [
@@ -15,9 +15,9 @@ sys.path.insert(0, file_folder + "/../peek")
15
15
 
16
16
  import peek
17
17
 
18
- import tempfile
19
18
 
20
- peek=peek.new(ignore_toml=True,output="stdout_nocolor")
19
+ peek = peek.new(ignore_toml=True, output="stdout_nocolor")
20
+
21
21
 
22
22
  class g:
23
23
  pass
@@ -68,9 +68,11 @@ hello='world'
68
68
  )
69
69
  assert result == hello
70
70
 
71
+
71
72
  def test_illegal_assignment():
72
73
  with pytest.raises(AttributeError):
73
- peek.colour = 'red'
74
+ peek.colour = "red"
75
+
74
76
 
75
77
  def test_two_arguments(capsys):
76
78
  hello = "world"
@@ -156,11 +158,22 @@ def test_calls():
156
158
  peek(a=1)
157
159
 
158
160
 
161
+ def test_repr_and_str(capsys):
162
+ print(str(peek))
163
+ out, err = capsys.readouterr()
164
+ assert out.startswith("peek with attributes:")
165
+ assert out.endswith(")\n")
166
+
167
+ print(repr(peek))
168
+ out, err = capsys.readouterr()
169
+ assert out.startswith("peek.new(")
170
+ assert out.endswith(")\n")
171
+
159
172
  def test_output(capsys, tmpdir):
160
173
  g.result = ""
161
174
 
162
175
  def my_output(s):
163
- g.result += s + "\n"
176
+ g.result += s
164
177
 
165
178
  hello = "world"
166
179
  peek(hello, output=print)
@@ -187,7 +200,6 @@ def test_output(capsys, tmpdir):
187
200
  out, err = capsys.readouterr()
188
201
  assert out == "hello='world'\n"
189
202
 
190
-
191
203
  path = Path(tmpdir) / "x0"
192
204
  peek(hello, output=path)
193
205
  out, err = capsys.readouterr()
@@ -235,38 +247,63 @@ def test_output(capsys, tmpdir):
235
247
  out, err = capsys.readouterr()
236
248
  assert out == "hello='world' [len=5]\n"
237
249
 
238
- def test_show_time(capsys):
239
- hello = "world"
240
- peek(hello, show_time=True)
241
- out, err = capsys.readouterr()
242
- assert out.endswith("hello='world'\n")
243
- assert "@ " in err
244
250
 
245
- def test_show_delta(capsys):
246
- hello = "world"
247
- peek(hello, show_delta=True)
248
- out, err = capsys.readouterr()
249
- assert out.endswith("hello='world'\n")
250
- assert "delta=" in err
251
+ def test_show_time(capsys):
252
+ hello = "world"
253
+ peek(hello, show_time=True)
254
+ out, err = capsys.readouterr()
255
+ assert out.endswith("hello='world'\n")
256
+ assert "@ " in out
251
257
 
252
- def test_as_str(capsys):
253
- hello = "world"
254
- s = peek(hello, as_str=True)
255
- peek(hello)
256
- out, err = capsys.readouterr()
257
- assert out == s
258
258
 
259
- with pytest.raises(TypeError):
259
+ def test_show_delta(capsys):
260
+ hello = "world"
261
+ peek(hello, show_delta=True)
262
+ out, err = capsys.readouterr()
263
+ assert out.endswith("hello='world'\n")
264
+ assert "delta=" in out
265
+
260
266
 
261
- @peek(as_str=True)
262
- def add2(x):
263
- return x + 2
267
+ def test_as_str(capsys):
268
+ hello = "world"
269
+ s = peek(hello, as_str=True)
270
+ peek(hello)
271
+ out, err = capsys.readouterr()
272
+ assert out == s
264
273
 
265
- with pytest.raises(TypeError):
266
- with peek(as_str=True):
267
- pass
274
+ with pytest.raises(TypeError):
275
+
276
+ @peek(as_str=True)
277
+ def add2(x):
278
+ return x + 2
279
+
280
+ with pytest.raises(TypeError):
281
+ with peek(as_str=True):
282
+ pass
268
283
 
269
284
 
285
+ def test_print(capsys):
286
+ peek.print(*range(4))
287
+ peek.print(*range(4), sep="|")
288
+ peek.print(*range(4), end="END\n")
289
+ peek.filter = "1<=level<=2"
290
+ for i in range(4):
291
+ peek.print(i, level=i)
292
+ out, err = capsys.readouterr()
293
+ peek.filter = ""
294
+ assert (
295
+ out
296
+ == """\
297
+ 0 1 2 3
298
+ 0|1|2|3
299
+ 0 1 2 3END
300
+ 1
301
+ 2
302
+ """
303
+ )
304
+ with pytest.raises(AttributeError):
305
+ peek.print(sep="|", sepp="/")
306
+
270
307
  def test_clone():
271
308
  hello = "world"
272
309
  z = peek.clone()
@@ -284,7 +321,8 @@ def test_sort_dicts():
284
321
  s1 = peek(world, sort_dicts=False, as_str=True)
285
322
  s2 = peek(world, sort_dicts=True, as_str=True)
286
323
  if sys.version_info >= (3, 8):
287
- assert s0 == s1 == "world={'EN': 'world', 'NL': 'wereld', 'FR': 'monde', 'DE': 'Welt'}\n"
324
+ assert s0 == "world={'EN': 'world', 'NL': 'wereld', 'FR': 'monde', 'DE': 'Welt'}\n"
325
+ assert s1 == "world={'EN': 'world', 'NL': 'wereld', 'FR': 'monde', 'DE': 'Welt'}\n"
288
326
  assert s2 == "world={'DE': 'Welt', 'EN': 'world', 'FR': 'monde', 'NL': 'wereld'}\n"
289
327
  else:
290
328
  assert s0 == s1 == s2 == "world={'DE': 'Welt', 'EN': 'world', 'FR': 'monde', 'NL': 'wereld'}\n"
@@ -337,24 +375,27 @@ lines=
337
375
  """
338
376
  )
339
377
 
378
+
340
379
  def test_filter(capsys):
341
380
  def gen():
342
381
  for level, color in enumerate("- blue red green blue".split()):
343
382
  peek(level, level=level, color=color)
344
383
 
345
- peek.filter="True"
384
+ peek.filter = "True"
346
385
  gen()
347
- peek.filter="level >=2"
386
+ peek.filter = "level >=2"
348
387
  gen()
349
- peek.filter="level >=2"
388
+ peek.filter = "level >=2"
350
389
  gen()
351
- peek.filter="level >=2 and color=='blue'"
390
+ peek.filter = "level >=2 and color=='blue'"
352
391
  gen()
353
- peek.filter=""
392
+ peek.filter = ""
354
393
  gen()
355
394
 
356
395
  out, err = capsys.readouterr()
357
- assert out == """\
396
+ assert (
397
+ out
398
+ == """\
358
399
  level=0
359
400
  level=1
360
401
  level=2
@@ -372,26 +413,29 @@ level=1
372
413
  level=2
373
414
  level=3
374
415
  level=4
375
- """
416
+ """
417
+ )
418
+
376
419
 
377
420
  @pytest.mark.skipif(Pythonista, reason="Pythonista does not generate ansi codes")
378
421
  def test_color(capsys):
379
- peek(10*10, output="stdout")
422
+ peek(10 * 10, output="stdout")
423
+ peek(10 * 10, color="red", output="stdout")
380
424
  out, err = capsys.readouterr()
381
- assert out == '\x1b[0m10*10=100\x1b[0m\n'
425
+ assert out == "10 * 10=100\n\x1b[0;31m10 * 10=100\n\x1b[0m"
382
426
 
383
427
 
384
428
  def test_incorrect_filter():
385
429
  with pytest.raises(AttributeError):
386
- peek.filter="color='blue'"
430
+ peek.filter = "color='blue'"
387
431
 
388
432
  with pytest.raises(AttributeError):
389
- peek.filter="colour=='blue'"
433
+ peek.filter = "colour=='blue'"
434
+
390
435
 
391
436
  def test_decorator(capsys):
392
437
  peek.fix_perf_counter(0)
393
438
 
394
-
395
439
  @peek()
396
440
  def div(x, y):
397
441
  return x / y
@@ -486,6 +530,7 @@ called __mul__(Number(2), Number(3))
486
530
  """
487
531
  )
488
532
 
533
+
489
534
  @pytest.mark.skipif(Pythonista, reason="Pythonista problem")
490
535
  def test_context_manager(capsys):
491
536
  peek.fix_perf_counter(0)
@@ -762,40 +807,6 @@ def test_traceback(capsys):
762
807
  assert out.count("traceback") == 2
763
808
 
764
809
 
765
- @pytest.mark.skipif(Pythonista, reason="Pythonista problem")
766
- def test_enforce_line_length(capsys):
767
- s = 80 * "*"
768
- with peek.preserve():
769
- peek.prefix = "peek| "
770
- peek.line_length = 80
771
- peek(s)
772
- peek(s, enforce_line_length=True)
773
- out, err = capsys.readouterr()
774
- assert (
775
- out
776
- == """\
777
- peek|
778
- s='********************************************************************************'
779
- peek|
780
- s='*************************************************************************
781
- """
782
- )
783
- with peek.preserve():
784
- peek.configure(line_length=20, show_line_number=True)
785
- peek()
786
- out1, err = capsys.readouterr()
787
- peek(enforce_line_length=True)
788
- out2, err = capsys.readouterr()
789
- out1 = out1.rstrip("\n")
790
- out2 = out2.rstrip("\n")
791
- assert len(out2) == 20
792
- assert out1[10:20] == out2[10:20]
793
- assert len(out1) > 20
794
- res = peek("abcdefghijklmnopqrstuvwxyz", pr="", enforce_line_length=1, ll=20, as_str=True).rstrip("\n")
795
- assert res == "'abcdefghijklmnopqrs"
796
- assert len(res) == 20
797
-
798
-
799
810
  def test_check_output(capsys, tmpdir):
800
811
  """special Pythonista code, as that does not reload x1 and x2"""
801
812
  if "x1" in sys.modules:
@@ -893,6 +904,27 @@ def test():
893
904
  """
894
905
  )
895
906
 
907
+
908
+ def test_prefix_variants(capsys):
909
+ n = 1
910
+ peek.prefix = lambda: f"{n:<2d}"
911
+ peek(10 * 10)
912
+ n = 2
913
+ peek(10 * 10)
914
+ peek.prefix = 1
915
+ peek(10 * 10)
916
+ out, err = capsys.readouterr()
917
+ assert (
918
+ out
919
+ == """\
920
+ 1 10 * 10=100
921
+ 2 10 * 10=100
922
+ 110 * 10=100
923
+ """
924
+ )
925
+ peek.prefix = ""
926
+
927
+
896
928
  def test_propagation():
897
929
  with peek.preserve():
898
930
  y0 = peek.fork()
@@ -956,6 +988,22 @@ def test_delta_propagation():
956
988
  assert 100 < y2.delta < 110
957
989
 
958
990
 
991
+ def test_end(capsys):
992
+ a = 12
993
+ b = 4 * ["test"]
994
+ c = 1
995
+ peek(a, end=" ")
996
+ peek(b, end=" ")
997
+ peek(c)
998
+ out, err = capsys.readouterr()
999
+ assert (
1000
+ out
1001
+ == """\
1002
+ a=12 b=['test', 'test', 'test', 'test'] c=1
1003
+ """
1004
+ )
1005
+
1006
+
959
1007
  def test_separator(capsys):
960
1008
  a = 12
961
1009
  b = 4 * ["test"]
@@ -992,7 +1040,6 @@ a = 12, b = ['test', 'test', 'test', 'test']
992
1040
  )
993
1041
 
994
1042
 
995
-
996
1043
  def test_context_separator(capsys):
997
1044
  a = 12
998
1045
  b = 2 * ["test"]
@@ -1081,4 +1128,3 @@ hello='world'
1081
1128
 
1082
1129
  if __name__ == "__main__":
1083
1130
  pytest.main(["-vv", "-s", "-x", __file__])
1084
-