peek-python 1.4.4.post0__tar.gz → 1.5.0__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.
- peek_python-1.4.4.post0/README.md → peek_python-1.5.0/PKG-INFO +1211 -1312
- peek_python-1.4.4.post0/peek_python.egg-info/PKG-INFO → peek_python-1.5.0/README.md +1197 -1326
- {peek_python-1.4.4.post0 → peek_python-1.5.0}/peek/peek.py +9 -34
- {peek_python-1.4.4.post0 → peek_python-1.5.0/peek_python.egg-info}/PKG-INFO +87 -202
- {peek_python-1.4.4.post0 → peek_python-1.5.0}/pyproject.toml +1 -1
- {peek_python-1.4.4.post0 → peek_python-1.5.0}/tests/test_peek.py +23 -44
- {peek_python-1.4.4.post0 → peek_python-1.5.0}/license.txt +0 -0
- {peek_python-1.4.4.post0 → peek_python-1.5.0}/peek/__init__.py +0 -0
- {peek_python-1.4.4.post0 → peek_python-1.5.0}/peek_python.egg-info/SOURCES.txt +0 -0
- {peek_python-1.4.4.post0 → peek_python-1.5.0}/peek_python.egg-info/dependency_links.txt +0 -0
- {peek_python-1.4.4.post0 → peek_python-1.5.0}/peek_python.egg-info/top_level.txt +0 -0
- {peek_python-1.4.4.post0 → peek_python-1.5.0}/setup.cfg +0 -0
|
@@ -1,1312 +1,1211 @@
|
|
|
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
|
-
add2(1000)
|
|
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
|
-
add2
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
add2(
|
|
183
|
-
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
```
|
|
279
|
-
peek()
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
peek
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
peek(12)
|
|
354
|
-
```
|
|
355
|
-
will print
|
|
356
|
-
```
|
|
357
|
-
==> 12
|
|
358
|
-
```
|
|
359
|
-
It is
|
|
360
|
-
```
|
|
361
|
-
peek.prefix
|
|
362
|
-
peek(12)
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
```
|
|
380
|
-
==> 12
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
hello
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
peek
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
to
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
shout()
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
```
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
File "c:\Users\Ruud\Dropbox (Personal)\Apps\Python Ruud\peek\x.py", line
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
peek
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
'0123456789',
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
```
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
d=
|
|
705
|
-
....
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
```
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
a
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
```
|
|
791
|
-
a=
|
|
792
|
-
peek
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
```
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
a
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
```
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
peek
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
f
|
|
845
|
-
|
|
846
|
-
```
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
```
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
```
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
```
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
```
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
peek
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
```
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
```
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
peek
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
peek
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
peek
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
peek.
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
peek(
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
```
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
of
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
>> hello = "world"
|
|
1213
|
-
>>> peek(hello, hello * 2)
|
|
1214
|
-
'hello', 'hellohello'
|
|
1215
|
-
('hello', 'hellohello')
|
|
1216
|
-
```
|
|
1217
|
-
* line numbers are never shown
|
|
1218
|
-
* use as a decorator is only supported when you used as `peek(decorator=True)` or `peek(d=1)`
|
|
1219
|
-
* use as a context manager is only supported when used as `peek(context_manager=True)`or `peek(cm=1)`
|
|
1220
|
-
|
|
1221
|
-
# Alternative to `peek`
|
|
1222
|
-
|
|
1223
|
-
Sometimes, even peek is too long during a debug session or it is not suitable to use the name peek.
|
|
1224
|
-
|
|
1225
|
-
In that case, it is possible to use p instead
|
|
1226
|
-
```
|
|
1227
|
-
from peek import p
|
|
1228
|
-
```
|
|
1229
|
-
The `p` object is a *fork* of peek. That means that attributes of `peek` are propagated to `p`, unless overridden.
|
|
1230
|
-
|
|
1231
|
-
# Alternative installation
|
|
1232
|
-
|
|
1233
|
-
With `install peek from github.py`, you can install the peek.py directly from GitHub to the site packages (as if it was a pip install).
|
|
1234
|
-
|
|
1235
|
-
With `install peek.py`, you can install the peek.py in your current directory to the site packages (as if it was a pip install).
|
|
1236
|
-
|
|
1237
|
-
Both files can be found in the GitHub repository (https://github.com/salabim/peek).
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
# Limitations
|
|
1241
|
-
|
|
1242
|
-
It is not possible to use peek:
|
|
1243
|
-
* from a frozen application (e.g. packaged with PyInstaller)
|
|
1244
|
-
* when the underlying source code has changed during execution
|
|
1245
|
-
|
|
1246
|
-
# Implementation details
|
|
1247
|
-
|
|
1248
|
-
Although not important for using the package, here are some implementation details:
|
|
1249
|
-
* peek.py contains the complete source of the asttokens, executing and six packages, in
|
|
1250
|
-
order to offer the required source lookups, without any dependencies
|
|
1251
|
-
* peek.py contains the complete source of pprint as of Python 3.13 in order to support the sort_dicts and underscore_numbers parameter
|
|
1252
|
-
* in order to support using peek() as a decorator and a context manager, peek caches the complete source of
|
|
1253
|
-
any source file that uses peek()
|
|
1254
|
-
|
|
1255
|
-
# Changelog
|
|
1256
|
-
|
|
1257
|
-
The changelog can be found here:
|
|
1258
|
-
|
|
1259
|
-
* https://github.com/salabim/peek/main/peek.md or
|
|
1260
|
-
* https://salabim.org/peek/changelog.html
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
# Acknowledgement
|
|
1264
|
-
|
|
1265
|
-
The **peek** pacakage is inspired by the **IceCream** package, but is a
|
|
1266
|
-
nearly complete rewrite. See https://github.com/gruns/icecream
|
|
1267
|
-
|
|
1268
|
-
Many thanks to the author Ansgar Grunseid / grunseid.com / grunseid@gmail.com .
|
|
1269
|
-
|
|
1270
|
-
The peek package is a rebrand of the **ycecream** package, with enhancements.
|
|
1271
|
-
|
|
1272
|
-
# Differences with IceCream
|
|
1273
|
-
|
|
1274
|
-
The peek module was originally a fork of **IceCream**, but has many differences:
|
|
1275
|
-
|
|
1276
|
-
```
|
|
1277
|
-
-------------------------------------------------------------------------------------------
|
|
1278
|
-
characteristic peek IceCream
|
|
1279
|
-
-------------------------------------------------------------------------------------------
|
|
1280
|
-
default name peek ic
|
|
1281
|
-
import method from peek import peek from icecream import ic
|
|
1282
|
-
dependencies none many
|
|
1283
|
-
number of files 1 several
|
|
1284
|
-
usable without installation yes no
|
|
1285
|
-
can be used as a decorator yes no
|
|
1286
|
-
can be used as a context manager yes no
|
|
1287
|
-
can show traceback yes no
|
|
1288
|
-
PEP8 (Pythonic) API yes no
|
|
1289
|
-
sorts dicts no by default, optional *) yes
|
|
1290
|
-
supports compact, indent,
|
|
1291
|
-
and underscore_numbers
|
|
1292
|
-
parameters of pprint yes **) no
|
|
1293
|
-
use from a REPL limited functionality no
|
|
1294
|
-
external configuration via json file no
|
|
1295
|
-
observes line_length correctly yes no
|
|
1296
|
-
benchmarking functionality yes no
|
|
1297
|
-
suppress f-strings at left hand optional no
|
|
1298
|
-
indentation 4 blanks (overridable) dependent on length of prefix
|
|
1299
|
-
forking and cloning yes no
|
|
1300
|
-
test script pytest unittest
|
|
1301
|
-
colourize no yes (can be disabled)
|
|
1302
|
-
-------------------------------------------------------------------------------------------
|
|
1303
|
-
*) under Python <= 3.7, dicts are always sorted (regardless of the sort_dicts attribute
|
|
1304
|
-
**) under Python <= 3.7, numbers are never underscored (regardless of the underscore_numnbers attribute
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
```
|
|
1308
|
-
  
|
|
1309
|
-
|
|
1310
|
-
 
|
|
1311
|
-

|
|
1312
|
-
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: peek-python
|
|
3
|
+
Version: 1.5.0
|
|
4
|
+
Summary: peek - debugging and benchmarking made easy
|
|
5
|
+
Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/salabim/ycecream
|
|
7
|
+
Project-URL: Repository, https://github.com/salabim/ycecream
|
|
8
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Requires-Python: >=3.6
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: license.txt
|
|
14
|
+
|
|
15
|
+
<img src="https://www.salabim.org/peek/peek_logo1.png">
|
|
16
|
+
|
|
17
|
+
# Introduction
|
|
18
|
+
|
|
19
|
+
Do you use `print()` or `log()` to debug your code?
|
|
20
|
+
If so, peek will make printing debug information really easy.
|
|
21
|
+
And on top of that, you get some basic benchmarking functionality.
|
|
22
|
+
|
|
23
|
+
# Table of contents
|
|
24
|
+
|
|
25
|
+
* [Installation](#installation)
|
|
26
|
+
|
|
27
|
+
* [Importing peek](#importing-peek)
|
|
28
|
+
|
|
29
|
+
* [Inspect variables and expressions](#inspect-variables-and-expressions)
|
|
30
|
+
|
|
31
|
+
* [Inspect execution](#inspect-execution)
|
|
32
|
+
|
|
33
|
+
* [Return value](#return-value)
|
|
34
|
+
|
|
35
|
+
* [Debug entry and exit of function calls](#debug-entry-and-exit-of-function-calls)
|
|
36
|
+
|
|
37
|
+
* [Benchmarking with peek](#benchmarking-with-peek)
|
|
38
|
+
|
|
39
|
+
* [Configuration](#configuration)
|
|
40
|
+
|
|
41
|
+
* [Return a string instead of sending to output](#return-a-string-instead-of-sending-to-output)
|
|
42
|
+
|
|
43
|
+
* [Disabling peek's output](#disabling-peeks-output)
|
|
44
|
+
|
|
45
|
+
* [Speeding up disabled peek](#speeding-up-disabled-peek)
|
|
46
|
+
|
|
47
|
+
* [Using peek as a substitute for `assert`](#using-peek-as-a-substitute-for-assert)
|
|
48
|
+
|
|
49
|
+
* [Interpreting the line number information](#interpreting-the-line-number-information)
|
|
50
|
+
|
|
51
|
+
* [Configuring at import time](#configuring-at-import-time)
|
|
52
|
+
|
|
53
|
+
* [Working with multiple instances of peek](#working-with-multiple-instances-of-peek)
|
|
54
|
+
|
|
55
|
+
* [Test script](#test-script)
|
|
56
|
+
|
|
57
|
+
* [Using peek in a REPL](#using-peek-in-a-repl)
|
|
58
|
+
|
|
59
|
+
* [Alternative to `peek`](#alternative-to-peek)
|
|
60
|
+
|
|
61
|
+
* [Alternative installation](#alternative-installation)
|
|
62
|
+
|
|
63
|
+
* [Limitations](#limitations)
|
|
64
|
+
|
|
65
|
+
* [Implementation details](#implementation-details)
|
|
66
|
+
|
|
67
|
+
* [Acknowledgement](#acknowledgement)
|
|
68
|
+
|
|
69
|
+
* [Changelog](#changelog)
|
|
70
|
+
|
|
71
|
+
* [Differences with IceCream](#differences-with-icecream)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# Installation
|
|
75
|
+
|
|
76
|
+
Installing peek with pip is easy.
|
|
77
|
+
```
|
|
78
|
+
pip install peek-python
|
|
79
|
+
```
|
|
80
|
+
or when you want to upgrade,
|
|
81
|
+
```
|
|
82
|
+
pip install peek-python --upgrade
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Alternatively, peek.py can be juist copied into you current work directory from GitHub (https://github.com/salabim/peek).
|
|
86
|
+
|
|
87
|
+
No dependencies!
|
|
88
|
+
|
|
89
|
+
# Importing peek
|
|
90
|
+
|
|
91
|
+
All you need is:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
import peek
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
, or the more conventional, but more verbose
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
from peek import peek
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
# Inspect variables and expressions
|
|
104
|
+
|
|
105
|
+
Have you ever printed variables or expressions to debug your program? If you've
|
|
106
|
+
ever typed something like
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
print(add2(1000))
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
or the more thorough
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
print("add2(1000)", add2(1000)))
|
|
116
|
+
```
|
|
117
|
+
or:
|
|
118
|
+
```
|
|
119
|
+
print(f"{add2(1000)=}")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
then `peek()` is here to help. With arguments, `peek()` inspects itself and prints
|
|
123
|
+
both its own arguments and the values of those arguments.
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
def add2(i):
|
|
127
|
+
return i + 2
|
|
128
|
+
|
|
129
|
+
peek(add2(1000))
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
prints
|
|
133
|
+
```
|
|
134
|
+
add2(1000)=1002
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Similarly,
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
class X:
|
|
141
|
+
a = 3
|
|
142
|
+
world = {"EN": "world", "NL": "wereld", "FR": "monde", "DE": "Welt"}
|
|
143
|
+
|
|
144
|
+
peek(world, X.a)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
prints
|
|
148
|
+
```
|
|
149
|
+
world={"EN": "world ", "NL": "wereld", "FR": "monde", "DE": "Welt"}, X.a: 3
|
|
150
|
+
```
|
|
151
|
+
Just give `peek()` a variable or expression and you're done. Easy, or what?
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
# Inspect execution
|
|
155
|
+
|
|
156
|
+
Have you ever used `print()` to determine which parts of your program are
|
|
157
|
+
executed, and in which order they're executed? For example, if you've ever added
|
|
158
|
+
print statements to debug code like
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
def add2(i):
|
|
162
|
+
print("***add2 1")
|
|
163
|
+
result = i + 2
|
|
164
|
+
print("***add2 2")
|
|
165
|
+
return result
|
|
166
|
+
```
|
|
167
|
+
then `peek()` helps here, too. Without arguments, `peek()` inspects itself and
|
|
168
|
+
prints the calling line number and -if applicable- the file name and parent function.
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
def add2(i):
|
|
172
|
+
peek()
|
|
173
|
+
result = i + 2
|
|
174
|
+
peek()
|
|
175
|
+
return result
|
|
176
|
+
peek(add2(1000))
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
prints something like
|
|
180
|
+
```
|
|
181
|
+
#3 in add2()
|
|
182
|
+
#5 in add2()
|
|
183
|
+
add2(1000)=1002
|
|
184
|
+
```
|
|
185
|
+
Just call `peek()` and you're done. Isn't that easy?
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
# Return Value
|
|
189
|
+
|
|
190
|
+
`peek()` returns its argument(s), so `peek()` can easily be inserted into
|
|
191
|
+
pre-existing code.
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
def add2(i):
|
|
195
|
+
return i + 2
|
|
196
|
+
b = peek(add2(1000))
|
|
197
|
+
peek(b)
|
|
198
|
+
```
|
|
199
|
+
prints
|
|
200
|
+
```
|
|
201
|
+
add2(1000)=1002
|
|
202
|
+
b=1002
|
|
203
|
+
```
|
|
204
|
+
# Debug entry and exit of function calls
|
|
205
|
+
|
|
206
|
+
When you apply `peek()` as a decorator to a function or method, both the entry and exit can be tracked.
|
|
207
|
+
The (keyword) arguments passed will be shown and upon return, the return value.
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
@peek()
|
|
211
|
+
def mul(x, peek):
|
|
212
|
+
return x * peek
|
|
213
|
+
|
|
214
|
+
print(mul(5, 7))
|
|
215
|
+
```
|
|
216
|
+
prints
|
|
217
|
+
```
|
|
218
|
+
called mul(5, 7)
|
|
219
|
+
returned 35 from mul(5, 7) in 0.000006 seconds
|
|
220
|
+
35
|
|
221
|
+
```
|
|
222
|
+
It is possible to suppress the print-out of either the enter or the exit information with
|
|
223
|
+
the show_enter and show_exit parameters, like:
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
@peek(show_exit=False)
|
|
227
|
+
def mul(x, peek):
|
|
228
|
+
return x * peek
|
|
229
|
+
|
|
230
|
+
print(mul(5, 7))
|
|
231
|
+
```
|
|
232
|
+
prints
|
|
233
|
+
```
|
|
234
|
+
called mul(5, 7)
|
|
235
|
+
35
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
# Benchmarking with peek
|
|
239
|
+
|
|
240
|
+
If you decorate a function or method with peek(), you will be offered the duration between entry and exit (in seconds) as a bonus.
|
|
241
|
+
|
|
242
|
+
That opens the door to simple benchmarking, like:
|
|
243
|
+
```
|
|
244
|
+
import time
|
|
245
|
+
|
|
246
|
+
@peek(show_enter=False,show_line_number=True)
|
|
247
|
+
def do_sort(i):
|
|
248
|
+
n = 10 ** i
|
|
249
|
+
x = sorted(list(range(n)))
|
|
250
|
+
return f"{n:9d}"
|
|
251
|
+
|
|
252
|
+
for i in range(8):
|
|
253
|
+
do_sort(i)
|
|
254
|
+
```
|
|
255
|
+
the ouput will show the effects of the population size on the sort speed:
|
|
256
|
+
```
|
|
257
|
+
#5 ==> returned ' 1' from do_sort(0) in 0.000027 seconds
|
|
258
|
+
#5 ==> returned ' 10' from do_sort(1) in 0.000060 seconds
|
|
259
|
+
#5 ==> returned ' 100' from do_sort(2) in 0.000748 seconds
|
|
260
|
+
#5 ==> returned ' 1000' from do_sort(3) in 0.001897 seconds
|
|
261
|
+
#5 ==> returned ' 10000' from do_sort(4) in 0.002231 seconds
|
|
262
|
+
#5 ==> returned ' 100000' from do_sort(5) in 0.024014 seconds
|
|
263
|
+
#5 ==> returned ' 1000000' from do_sort(6) in 0.257504 seconds
|
|
264
|
+
#5 ==> returned ' 10000000' from do_sort(7) in 1.553495 seconds
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
It is also possible to time any code by using peek() as a context manager, e.g.
|
|
268
|
+
```
|
|
269
|
+
with peek():
|
|
270
|
+
time.sleep(1)
|
|
271
|
+
```
|
|
272
|
+
wil print something like
|
|
273
|
+
```
|
|
274
|
+
enter
|
|
275
|
+
exit in 1.000900 seconds
|
|
276
|
+
```
|
|
277
|
+
You can include parameters here as well:
|
|
278
|
+
```
|
|
279
|
+
with peek(show_line_number=True, show_time=True):
|
|
280
|
+
time.sleep(1)
|
|
281
|
+
```
|
|
282
|
+
will print somethink like:
|
|
283
|
+
```
|
|
284
|
+
#8 @ 13:20:32.605903 ==> enter
|
|
285
|
+
#8 @ 13:20:33.609519 ==> exit in 1.003358 seconds
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Finally, to help with timing code, you can request the current delta with
|
|
289
|
+
```
|
|
290
|
+
peek.delta
|
|
291
|
+
```
|
|
292
|
+
or (re)set it with
|
|
293
|
+
```
|
|
294
|
+
peek.delta = 0
|
|
295
|
+
```
|
|
296
|
+
So, e.g. to time a section of code:
|
|
297
|
+
```
|
|
298
|
+
peek.delta = 0
|
|
299
|
+
time.sleep(1)
|
|
300
|
+
duration = peek.delta
|
|
301
|
+
peek(duration)
|
|
302
|
+
```
|
|
303
|
+
might print something like:
|
|
304
|
+
```
|
|
305
|
+
duration=1.0001721999999997
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
# Configuration
|
|
309
|
+
|
|
310
|
+
For the configuration, it is important to realize that `peek` is an instance of a class, which has
|
|
311
|
+
a number of configuration attributes:
|
|
312
|
+
|
|
313
|
+
```
|
|
314
|
+
------------------------------------------------------
|
|
315
|
+
attribute alternative default
|
|
316
|
+
------------------------------------------------------
|
|
317
|
+
prefix pr ""
|
|
318
|
+
output o "stdout"
|
|
319
|
+
serialize pprint.pformat
|
|
320
|
+
show_line_number sln False
|
|
321
|
+
show_time st False
|
|
322
|
+
show_delta sd False
|
|
323
|
+
show_enter se True
|
|
324
|
+
show_exit sx True
|
|
325
|
+
show_traceback stb False
|
|
326
|
+
sort_dicts sdi False
|
|
327
|
+
underscore_numbers un False
|
|
328
|
+
enabled e True
|
|
329
|
+
line_length ll 160
|
|
330
|
+
compact c False
|
|
331
|
+
indent i 1
|
|
332
|
+
depth de 1000000
|
|
333
|
+
wrap_indent wi " "
|
|
334
|
+
separator sep ", "
|
|
335
|
+
context_separator cs " ==> "
|
|
336
|
+
equals_separator es "="
|
|
337
|
+
values_only vo False
|
|
338
|
+
value_only_for_fstrings voff False
|
|
339
|
+
return_none rn False
|
|
340
|
+
enforce_line_length ell False
|
|
341
|
+
delta dl 0
|
|
342
|
+
------------------------------------------------------
|
|
343
|
+
```
|
|
344
|
+
It is perfectly ok to set/get any of these attributes directly, like
|
|
345
|
+
```
|
|
346
|
+
peek.prefix = "==> "
|
|
347
|
+
print(peek.prefix)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
But, it is also possible to apply configuration directly, only here, in the call to `peek`:
|
|
351
|
+
So, it is possible to say
|
|
352
|
+
```
|
|
353
|
+
peek(12, prefix="==> ")
|
|
354
|
+
```
|
|
355
|
+
, which will print
|
|
356
|
+
```
|
|
357
|
+
==> 12
|
|
358
|
+
```
|
|
359
|
+
It is also possible to configure peek permanently with the configure method.
|
|
360
|
+
```
|
|
361
|
+
peek.configure(prefix="==> ")
|
|
362
|
+
peek(12)
|
|
363
|
+
```
|
|
364
|
+
will print
|
|
365
|
+
```
|
|
366
|
+
==> 12
|
|
367
|
+
```
|
|
368
|
+
It is arguably easier to say:
|
|
369
|
+
```
|
|
370
|
+
peek.prefix = "==> "
|
|
371
|
+
peek(12)
|
|
372
|
+
```
|
|
373
|
+
or even
|
|
374
|
+
```
|
|
375
|
+
peek.pr = "==> "
|
|
376
|
+
peek(12)
|
|
377
|
+
```
|
|
378
|
+
to print
|
|
379
|
+
```
|
|
380
|
+
==> 12
|
|
381
|
+
```
|
|
382
|
+
Yet another way to configure peek is to get a new instance of peek with peek.new() and the required configuration:
|
|
383
|
+
```
|
|
384
|
+
z = peek.new(prefix="==> ")
|
|
385
|
+
z(12)
|
|
386
|
+
```
|
|
387
|
+
will print
|
|
388
|
+
```
|
|
389
|
+
==> 12
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Or, yet another possibility is to clone peek (optionally with modified attributes):
|
|
393
|
+
```
|
|
394
|
+
peek1 = peek.clone(show_time=True)
|
|
395
|
+
peek2 = peek.clone()
|
|
396
|
+
peek2.show_time = True
|
|
397
|
+
```
|
|
398
|
+
After this `peek1` and `peek2` will behave similarly (but they are not the same!)
|
|
399
|
+
|
|
400
|
+
## prefix / pr
|
|
401
|
+
```
|
|
402
|
+
peek('world', prefix='hello -> ')
|
|
403
|
+
```
|
|
404
|
+
prints
|
|
405
|
+
```
|
|
406
|
+
hello -> 'world'
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
`prefix` can be a function, too.
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
import time
|
|
413
|
+
def unix_timestamp():
|
|
414
|
+
return f"{int(time.time())} "
|
|
415
|
+
hello = "world"
|
|
416
|
+
peek.prefix = unix_timestamp
|
|
417
|
+
peek(hello)
|
|
418
|
+
```
|
|
419
|
+
prints
|
|
420
|
+
```
|
|
421
|
+
1613635601 hello='world'
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## output / o
|
|
425
|
+
This will allow the output to be handled by something else than the default (output being written to stdout).
|
|
426
|
+
|
|
427
|
+
The `output` attribute can be
|
|
428
|
+
|
|
429
|
+
* a callable that accepts at least one parameter (the text to be printed)
|
|
430
|
+
* a string or Path object that will be used as the filename
|
|
431
|
+
* a text file that is open for writing/appending
|
|
432
|
+
|
|
433
|
+
In the example below,
|
|
434
|
+
```
|
|
435
|
+
import sys
|
|
436
|
+
peek(1, output=print)
|
|
437
|
+
peek(2, output=sys.stderr)
|
|
438
|
+
with open("test", "a+") as f:
|
|
439
|
+
peek(3, output=f)
|
|
440
|
+
peek(4, output="")
|
|
441
|
+
```
|
|
442
|
+
* `1` will be printed to stdout
|
|
443
|
+
* `2` will be printed to stderr
|
|
444
|
+
* `3` will be appended to the file test
|
|
445
|
+
* nothing will be printed/written
|
|
446
|
+
|
|
447
|
+
As `output` may be a callable, you can even use this to automatically log any `peek` output:
|
|
448
|
+
```
|
|
449
|
+
import logging
|
|
450
|
+
logging.basicConfig(level="INFO")
|
|
451
|
+
log = logging.getLogger("demo")
|
|
452
|
+
peek.configure(output=log.info)
|
|
453
|
+
a = {1, 2, 3, 4, 5}
|
|
454
|
+
peek(a)
|
|
455
|
+
a.remove(4)
|
|
456
|
+
peek(a)
|
|
457
|
+
```
|
|
458
|
+
will print to stdout:
|
|
459
|
+
```
|
|
460
|
+
INFO:demo:a={1, 2, 3, 4, 5}
|
|
461
|
+
INFO:demo:a={1, 2, 3, 5}
|
|
462
|
+
```
|
|
463
|
+
Finally, you can specify the following strings:
|
|
464
|
+
```
|
|
465
|
+
"stderr" to print to stderr
|
|
466
|
+
"stdout" to print to stdout
|
|
467
|
+
"null" or "" to completely ignore (dummy) output
|
|
468
|
+
"logging.debug" to use logging.debug
|
|
469
|
+
"logging.info" to use logging.info
|
|
470
|
+
"logging.warning" to use logging.warning
|
|
471
|
+
"logging.error" to use logging.error
|
|
472
|
+
"logging.critical" to use logging.critical
|
|
473
|
+
```
|
|
474
|
+
E.g.
|
|
475
|
+
```
|
|
476
|
+
import sys
|
|
477
|
+
peek.output = "stderr"
|
|
478
|
+
```
|
|
479
|
+
to print to stderr.
|
|
480
|
+
|
|
481
|
+
## serialize
|
|
482
|
+
This will allow to specify how argument values are to be serialized to displayable strings.
|
|
483
|
+
The default is `pformat` (from `pprint`), but this can be changed.
|
|
484
|
+
For example, to handle non-standard datatypes in a custom fashion.
|
|
485
|
+
The serialize function should accept at least one parameter.
|
|
486
|
+
The function may optionally accept the keyword arguments `width` and `sort_dicts`, `compact`, `indent`, `underscore_numbers` and `depth`.
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
def add_len(obj):
|
|
490
|
+
if hasattr(obj, "__len__"):
|
|
491
|
+
add = f" [len={len(obj)}]"
|
|
492
|
+
else:
|
|
493
|
+
add = ""
|
|
494
|
+
return f"{repr(obj)}{add}"
|
|
495
|
+
|
|
496
|
+
l7 = list(range(7))
|
|
497
|
+
hello = "world"
|
|
498
|
+
peek(7, hello, l7, serialize=add_len)
|
|
499
|
+
```
|
|
500
|
+
prints
|
|
501
|
+
```
|
|
502
|
+
7, hello='world' [len=5], l7=[0, 1, 2, 3, 4, 5, 6] [len=7]
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
## show_line_number / sln
|
|
506
|
+
If True, adds the `peek()` call's line number and possibly the filename and parent function to `peek()`'s output.
|
|
507
|
+
|
|
508
|
+
```
|
|
509
|
+
peek.configure(show_line_number=True)
|
|
510
|
+
def shout():
|
|
511
|
+
hello="world"
|
|
512
|
+
peek(hello)
|
|
513
|
+
shout()
|
|
514
|
+
```
|
|
515
|
+
prints something like
|
|
516
|
+
```
|
|
517
|
+
#5 in shout() ==> hello='world'
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
If "no parent" or "n", the parent function will not be shown.
|
|
521
|
+
```
|
|
522
|
+
peek.show_line_number = "n"
|
|
523
|
+
def shout():
|
|
524
|
+
hello="world"
|
|
525
|
+
peek(hello)
|
|
526
|
+
shout()
|
|
527
|
+
```
|
|
528
|
+
prints something like
|
|
529
|
+
```
|
|
530
|
+
#5 ==> hello='world'
|
|
531
|
+
```
|
|
532
|
+
Note that if you call `peek` without any arguments, the line number is always shown, regardless of the status `show_line_number`.
|
|
533
|
+
|
|
534
|
+
See below for an explanation of the information provided.
|
|
535
|
+
|
|
536
|
+
## show_time / st
|
|
537
|
+
If True, adds the current time to `peek()`'s output.
|
|
538
|
+
|
|
539
|
+
```
|
|
540
|
+
peek.configure(show_time=True)
|
|
541
|
+
hello="world"
|
|
542
|
+
peek(hello)
|
|
543
|
+
```
|
|
544
|
+
prints something like
|
|
545
|
+
```
|
|
546
|
+
@ 13:01:47.588125 ==> hello='world'
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
## show_delta / sd
|
|
550
|
+
If True, adds the number of seconds since the start of the program to `peek()`'s output.
|
|
551
|
+
```
|
|
552
|
+
import time
|
|
553
|
+
peek.show_delta = True
|
|
554
|
+
french = "bonjour le monde"
|
|
555
|
+
english = "hallo world"
|
|
556
|
+
peek(english)
|
|
557
|
+
time.sleep(1)
|
|
558
|
+
peek(french)
|
|
559
|
+
```
|
|
560
|
+
prints something like
|
|
561
|
+
```
|
|
562
|
+
delta=0.088 ==> english='hallo world'
|
|
563
|
+
delta=1.091 ==> french='bonjour le monde'
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
## show_enter / se
|
|
567
|
+
When used as a decorator or context manager, by default, peek ouputs a line when the decorated the
|
|
568
|
+
function is called or the context manager is entered.
|
|
569
|
+
|
|
570
|
+
With `show_enter=False` this line can be suppressed.
|
|
571
|
+
|
|
572
|
+
## show_exit / sx
|
|
573
|
+
When used as a decorator or context manager, by default, peek ouputs a line when the decorated the
|
|
574
|
+
function returned or the context manager is exited.
|
|
575
|
+
|
|
576
|
+
With `show_exit=False` this line can be suppressed.
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
## show_traceback / stb
|
|
580
|
+
When show_traceback is True, the ordinary output of peek() will be followed by a printout of the
|
|
581
|
+
traceback, similar to an error traceback.
|
|
582
|
+
|
|
583
|
+
```
|
|
584
|
+
def x():
|
|
585
|
+
peek(show_traceback=True)
|
|
586
|
+
|
|
587
|
+
x()
|
|
588
|
+
x()
|
|
589
|
+
```
|
|
590
|
+
prints
|
|
591
|
+
```
|
|
592
|
+
#4 in x()
|
|
593
|
+
Traceback (most recent call last)
|
|
594
|
+
File "c:\Users\Ruud\Dropbox (Personal)\Apps\Python Ruud\peek\x.py", line 6, in <module>
|
|
595
|
+
x()
|
|
596
|
+
File "c:\Users\Ruud\Dropbox (Personal)\Apps\Python Ruud\peek\x.py", line 4, in x
|
|
597
|
+
peek()
|
|
598
|
+
#4 in x()
|
|
599
|
+
Traceback (most recent call last)
|
|
600
|
+
File "c:\Users\Ruud\Dropbox (Personal)\Apps\Python Ruud\peek\x.py", line 7, in <module>
|
|
601
|
+
x()
|
|
602
|
+
File "c:\Users\Ruud\Dropbox (Personal)\Apps\Python Ruud\peek\x.py", line 4, in x
|
|
603
|
+
peek()
|
|
604
|
+
```
|
|
605
|
+
The `show_traceback` functionality is also available when peek is used as a decorator or context manager.
|
|
606
|
+
|
|
607
|
+
## line_length / ll
|
|
608
|
+
This attribute is used to specify the line length (for wrapping). The default is 160.
|
|
609
|
+
Peek tries to keep all output on one line, but if it can't it will wrap:
|
|
610
|
+
|
|
611
|
+
```
|
|
612
|
+
d = dict(a1=1,a2=dict(a=1,b=1,c=3),a3=list(range(10)))
|
|
613
|
+
peek(d)
|
|
614
|
+
peek(d, line_length=80)
|
|
615
|
+
```
|
|
616
|
+
prints
|
|
617
|
+
```
|
|
618
|
+
d={'a1': 1, 'a2': {'a': 1, 'b': 1, 'c': 3}, 'a3': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
|
|
619
|
+
d=
|
|
620
|
+
{'a1': 1,
|
|
621
|
+
'a2': {'a': 1, 'b': 1, 'c': 3},
|
|
622
|
+
'a3': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
## compact / c
|
|
626
|
+
This attribute is used to specify the compact parameter for `pformat` (see the pprint documentation
|
|
627
|
+
for details). `compact` is False by default.
|
|
628
|
+
|
|
629
|
+
```
|
|
630
|
+
a = 9 * ["0123456789"]
|
|
631
|
+
peek.line_length = 80
|
|
632
|
+
peek(a)
|
|
633
|
+
peek(a, compact=True)
|
|
634
|
+
```
|
|
635
|
+
prints
|
|
636
|
+
```
|
|
637
|
+
a=
|
|
638
|
+
['0123456789',
|
|
639
|
+
'0123456789',
|
|
640
|
+
'0123456789',
|
|
641
|
+
'0123456789',
|
|
642
|
+
'0123456789',
|
|
643
|
+
'0123456789',
|
|
644
|
+
'0123456789',
|
|
645
|
+
'0123456789',
|
|
646
|
+
'0123456789']
|
|
647
|
+
a=
|
|
648
|
+
['0123456789', '0123456789', '0123456789', '0123456789', '0123456789',
|
|
649
|
+
'0123456789', '0123456789', '0123456789', '0123456789']
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
## indent / i
|
|
653
|
+
This attribute is used to specify the indent parameter for `pformat` (see the pprint documentation
|
|
654
|
+
for details). `indent` is 1 by default.
|
|
655
|
+
|
|
656
|
+
```
|
|
657
|
+
s = "01234567890012345678900123456789001234567890"
|
|
658
|
+
peek.line_length = 80
|
|
659
|
+
peek( [s, [s]])
|
|
660
|
+
peek( [s, [s]], indent=4)
|
|
661
|
+
```
|
|
662
|
+
prints
|
|
663
|
+
```
|
|
664
|
+
[s, [s]]=
|
|
665
|
+
['01234567890012345678900123456789001234567890',
|
|
666
|
+
['01234567890012345678900123456789001234567890']]
|
|
667
|
+
[s, [s]]=
|
|
668
|
+
[ '01234567890012345678900123456789001234567890',
|
|
669
|
+
['01234567890012345678900123456789001234567890']]
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
## depth / de
|
|
673
|
+
This attribute is used to specify the depth parameter for `pformat` (see the pprint documentation
|
|
674
|
+
for details). `depth` is `1000000` by default.
|
|
675
|
+
|
|
676
|
+
```
|
|
677
|
+
s = "01234567890012345678900123456789001234567890"
|
|
678
|
+
peek([s,[s,[s,[s,s]]]])
|
|
679
|
+
peek([s,[s,[s,[s,s]]]], depth=3)
|
|
680
|
+
```
|
|
681
|
+
prints
|
|
682
|
+
```
|
|
683
|
+
[s,[s,[s,[s,s]]]]=
|
|
684
|
+
['01234567890012345678900123456789001234567890',
|
|
685
|
+
['01234567890012345678900123456789001234567890',
|
|
686
|
+
['01234567890012345678900123456789001234567890',
|
|
687
|
+
['01234567890012345678900123456789001234567890',
|
|
688
|
+
'01234567890012345678900123456789001234567890']]]]
|
|
689
|
+
[s,[s,[s,[s,s]]]]=
|
|
690
|
+
['01234567890012345678900123456789001234567890',
|
|
691
|
+
['01234567890012345678900123456789001234567890',
|
|
692
|
+
['01234567890012345678900123456789001234567890', [...]]]]
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
## wrap_indent / wi
|
|
696
|
+
This specifies the indent string if the output does not fit in the line_length (has to be wrapped).
|
|
697
|
+
Rather than a string, wrap_indent can be also be an integer, in which case the wrap_indent will be that amount of blanks.
|
|
698
|
+
The default is 4 blanks.
|
|
699
|
+
|
|
700
|
+
E.g.
|
|
701
|
+
```
|
|
702
|
+
d = dict(a1=1,a2=dict(a=1,b=1,c=3),a3=list(range(10)))
|
|
703
|
+
peek.line_length = 80
|
|
704
|
+
peek(d, wrap_indent=" ")
|
|
705
|
+
peek(d, wrap_indent="....")
|
|
706
|
+
peek(d, wrap_indent=2)
|
|
707
|
+
```
|
|
708
|
+
prints
|
|
709
|
+
```
|
|
710
|
+
d=
|
|
711
|
+
{'a1': 1,
|
|
712
|
+
'a2': {'a': 1, 'b': 1, 'c': 3},
|
|
713
|
+
'a3': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
|
|
714
|
+
d=
|
|
715
|
+
....{'a1': 1,
|
|
716
|
+
.... 'a2': {'a': 1, 'b': 1, 'c': 3},
|
|
717
|
+
.... 'a3': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
|
|
718
|
+
d=
|
|
719
|
+
{'a1': 1,
|
|
720
|
+
'a2': {'a': 1, 'b': 1, 'c': 3},
|
|
721
|
+
'a3': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
## enabled / e
|
|
725
|
+
Can be used to disable the output:
|
|
726
|
+
```
|
|
727
|
+
peek.enabled = False
|
|
728
|
+
s = 'the world is '
|
|
729
|
+
peek(s + 'perfect.')
|
|
730
|
+
peek.enabled = True
|
|
731
|
+
peek(s + 'on fire.')
|
|
732
|
+
```
|
|
733
|
+
prints
|
|
734
|
+
```
|
|
735
|
+
s + 'on fire.'='the world is on fire.'
|
|
736
|
+
```
|
|
737
|
+
and nothing about a perfect world.
|
|
738
|
+
|
|
739
|
+
## sort_dicts / sdi
|
|
740
|
+
By default, peek does not sort dicts (printed by pprint). However, it is possible to get the
|
|
741
|
+
default pprint behaviour (i.e. sorting dicts) with the sorted_dicts attribute:
|
|
742
|
+
|
|
743
|
+
```
|
|
744
|
+
world = {"EN": "world", "NL": "wereld", "FR": "monde", "DE": "Welt"}
|
|
745
|
+
peek(world))
|
|
746
|
+
peek(world, sort_dicts=False)
|
|
747
|
+
peek(world, sort_dicts=True)
|
|
748
|
+
```
|
|
749
|
+
prints
|
|
750
|
+
```
|
|
751
|
+
world={'EN': 'world', 'NL': 'wereld', 'FR': 'monde', 'DE': 'Welt'}
|
|
752
|
+
world={'EN': 'world', 'NL': 'wereld', 'FR': 'monde', 'DE': 'Welt'}
|
|
753
|
+
world={'DE': 'Welt', 'EN': 'world', 'FR': 'monde', 'NL': 'wereld'}
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
Note that under Python <=3.7, dicts are always printed sorted.
|
|
757
|
+
|
|
758
|
+
## underscore_numbers / un
|
|
759
|
+
|
|
760
|
+
By default, peek does not add underscores in big numbers (printed by pprint). However, it is possible to get the
|
|
761
|
+
default pprint behaviour with the underscore_numbers attribute:
|
|
762
|
+
|
|
763
|
+
```
|
|
764
|
+
numbers = dict(one= 1, thousand= 1000, million=1000000, x1234567890= 1234567890)
|
|
765
|
+
peek(numbers)
|
|
766
|
+
peek(numbers, underscore_numbers=True)
|
|
767
|
+
peek(numbers, un=False)
|
|
768
|
+
```
|
|
769
|
+
prints
|
|
770
|
+
```
|
|
771
|
+
numbers={'one': 1, 'thousand': 1000, 'million': 1000000, 'x1234567890': 1234567890}
|
|
772
|
+
numbers={'one': 1, 'thousand': 1_000, 'million': 1_000_000, 'x1234567890': 1_234_567_890}
|
|
773
|
+
numbers={'one': 1, 'thousand': 1000, 'million': 1000000, 'x1234567890': 1234567890}
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
## seperator / sep
|
|
777
|
+
|
|
778
|
+
By default, pairs (on one line) are separated by `, `.
|
|
779
|
+
It is possible to change this with the attribute ` separator`:
|
|
780
|
+
|
|
781
|
+
```
|
|
782
|
+
a = "abcd"
|
|
783
|
+
b = 1
|
|
784
|
+
c = 1000
|
|
785
|
+
d = list("peek")
|
|
786
|
+
peek(a, (b, c), d)
|
|
787
|
+
peek(a, (b, c), d, separator=" | ")
|
|
788
|
+
```
|
|
789
|
+
prints
|
|
790
|
+
```
|
|
791
|
+
a='abcd', (b,c)=(1, 1000), d=['peek', 'c', 'e', 'c', 'r', 'e', 'a', 'm']
|
|
792
|
+
a='abcd' | (b,c)=(1, 1000) | d=['peek', 'c', 'e', 'c', 'r', 'e', 'a', 'm']
|
|
793
|
+
```
|
|
794
|
+
Note that under Python <=3.7, numbers are never printed with underscores.
|
|
795
|
+
|
|
796
|
+
## context_separator / cs
|
|
797
|
+
|
|
798
|
+
By default the line_number, time and/or delta are followed by ` ==> `.
|
|
799
|
+
It is possible to change this with the attribute `context_separator`:
|
|
800
|
+
```
|
|
801
|
+
a = "abcd"
|
|
802
|
+
peek(a,show_time=True)
|
|
803
|
+
peek(a, show_time=True, context_separator = ' \u279c ')
|
|
804
|
+
```
|
|
805
|
+
prints:
|
|
806
|
+
```
|
|
807
|
+
@ 09:05:38.693840 ==> a='abcd'
|
|
808
|
+
@ 09:05:38.707914 ➜ a='abcd'
|
|
809
|
+
```
|
|
810
|
+
## equals_separator / es
|
|
811
|
+
By default name of a variable and its value are separated by `= `.
|
|
812
|
+
It is possible to change this with the attribute `equals_separator`:
|
|
813
|
+
|
|
814
|
+
```
|
|
815
|
+
a = "abcd"
|
|
816
|
+
peek(a)
|
|
817
|
+
peek(a, equals_separator = ' == ")
|
|
818
|
+
```
|
|
819
|
+
prints:
|
|
820
|
+
```
|
|
821
|
+
a='abcd'
|
|
822
|
+
a == 'abcd'
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
## values_only / vo
|
|
826
|
+
If False (the default), both the left-hand side (if possible) and the
|
|
827
|
+
value will be printed. If True, the left hand side will be suppressed:
|
|
828
|
+
```
|
|
829
|
+
hello = "world"
|
|
830
|
+
peek(hello, 2 * hello)
|
|
831
|
+
peek(hello, 2 * hello, values_only=True)
|
|
832
|
+
```
|
|
833
|
+
prints
|
|
834
|
+
```
|
|
835
|
+
hello='world', 2 * hello='worldworld'
|
|
836
|
+
'world', 'worldworld'
|
|
837
|
+
```
|
|
838
|
+
The values=True version of peek can be seen as a supercharged print/pprint.
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
## values_only_for_fstrings / voff
|
|
842
|
+
If False (the default), both the original f-string and the
|
|
843
|
+
value will be printed for f-strings.
|
|
844
|
+
If True, the left_hand side will be suppressed in case of an f-string:
|
|
845
|
+
|
|
846
|
+
```
|
|
847
|
+
x = 12.3
|
|
848
|
+
peek(f"{x:0.3e}")
|
|
849
|
+
peek.values_only_for_fstrings = True
|
|
850
|
+
peek(f"{x:0.3e}")
|
|
851
|
+
```
|
|
852
|
+
prints
|
|
853
|
+
```
|
|
854
|
+
f"{x:0.3e}"='1.230e+01'
|
|
855
|
+
'1.230e+01'
|
|
856
|
+
```
|
|
857
|
+
Note that if `values_only` is True, f-string will be suppressed, regardless of `values_only_for_fstrings`.
|
|
858
|
+
|
|
859
|
+
## return_none / rn
|
|
860
|
+
Normally, `peek()`returns the values passed directly, which is usually fine. However, when used in a notebook
|
|
861
|
+
or REPL, that value will be shown, and that can be annoying. Therefore, if `return_none`is True, `peek()`will
|
|
862
|
+
return None and thus not show anything.
|
|
863
|
+
```
|
|
864
|
+
a = 3
|
|
865
|
+
b = 4
|
|
866
|
+
print(peek(a, b))
|
|
867
|
+
peek.return_none = True
|
|
868
|
+
print(peek(a, b))
|
|
869
|
+
```
|
|
870
|
+
prints
|
|
871
|
+
```
|
|
872
|
+
a=3, b=4
|
|
873
|
+
(3, 4)
|
|
874
|
+
a=3, b=4
|
|
875
|
+
None
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
## enforce_line_length / ell
|
|
879
|
+
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.
|
|
880
|
+
|
|
881
|
+
## delta / dl
|
|
882
|
+
The delta attribute can be used to (re)set the current delta, e.g.
|
|
883
|
+
```
|
|
884
|
+
peek.dl = 0
|
|
885
|
+
print(peek.delta)
|
|
886
|
+
```
|
|
887
|
+
prints a value that id slightly more than 0.
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
## provided / pr
|
|
891
|
+
If provided is False, all output for this call will be suppressed.
|
|
892
|
+
If provided is True, output will be generated as usual (obeying the enabled attribute).
|
|
893
|
+
|
|
894
|
+
```
|
|
895
|
+
x = 1
|
|
896
|
+
peek("should print", provided=x > 0)
|
|
897
|
+
peek("should not print", provided=x < 0)
|
|
898
|
+
```
|
|
899
|
+
This will print
|
|
900
|
+
```
|
|
901
|
+
should print
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
# Return a string instead of sending to output
|
|
905
|
+
|
|
906
|
+
`peek(*args, as_str=True)` is like `peek(*args)` but the output is returned as a string instead
|
|
907
|
+
of written to output.
|
|
908
|
+
|
|
909
|
+
```
|
|
910
|
+
hello = "world"
|
|
911
|
+
s = peek(hello, as_str=True)
|
|
912
|
+
print(s, end="")
|
|
913
|
+
```
|
|
914
|
+
prints
|
|
915
|
+
```
|
|
916
|
+
hello='world'
|
|
917
|
+
```
|
|
918
|
+
|
|
919
|
+
Note that if enabled=False, the call will return the null string (`""`).
|
|
920
|
+
|
|
921
|
+
# Disabling peek's output
|
|
922
|
+
|
|
923
|
+
```
|
|
924
|
+
peek1 = peek.fork(show_delta=True)
|
|
925
|
+
peek(1)
|
|
926
|
+
peek1(2)
|
|
927
|
+
peek.enabled = False
|
|
928
|
+
peek(3)
|
|
929
|
+
peek1(4)
|
|
930
|
+
peek1.enabled = True
|
|
931
|
+
peek(5)
|
|
932
|
+
peek1(6)
|
|
933
|
+
print(peek1.enabled)
|
|
934
|
+
```
|
|
935
|
+
prints
|
|
936
|
+
```
|
|
937
|
+
1
|
|
938
|
+
delta=0.011826 ==> 2
|
|
939
|
+
5
|
|
940
|
+
delta=0.044893 ==> 6
|
|
941
|
+
True
|
|
942
|
+
```
|
|
943
|
+
Of course `peek()` continues to return its arguments when disabled, of course.
|
|
944
|
+
|
|
945
|
+
It is also possible to suppress output with the provided attribute (see above).
|
|
946
|
+
|
|
947
|
+
# Using peek as a substitute for `assert`
|
|
948
|
+
|
|
949
|
+
Peek has a method `assert_` that works like `assert`, but can be enabled or disabled with the enabled flag.
|
|
950
|
+
|
|
951
|
+
```
|
|
952
|
+
temperature = -1
|
|
953
|
+
peek.assert_(temperature > 0)
|
|
954
|
+
```
|
|
955
|
+
This will raise an AttributeError.
|
|
956
|
+
|
|
957
|
+
But
|
|
958
|
+
```
|
|
959
|
+
peek.enabled = False
|
|
960
|
+
temperature = -1
|
|
961
|
+
peek.assert_(temperature > 0)
|
|
962
|
+
```
|
|
963
|
+
will not.
|
|
964
|
+
|
|
965
|
+
Note that with the attribute propagation method, you can in effect have a layered assert system.
|
|
966
|
+
|
|
967
|
+
# Interpreting the line number information
|
|
968
|
+
|
|
969
|
+
When `show_line_number` is True or peek() is used without any parameters, the output will contain the line number like:
|
|
970
|
+
```
|
|
971
|
+
#3 ==> a='abcd'
|
|
972
|
+
```
|
|
973
|
+
If the line resides in another file than the main file, the filename (without the path) will be shown as well:
|
|
974
|
+
```
|
|
975
|
+
#30[foo.py] ==> foo='Foo'
|
|
976
|
+
```
|
|
977
|
+
And finally when used in a function or method, that function/method will be shown as well:
|
|
978
|
+
```
|
|
979
|
+
#456[foo.py] in square_root ==> x=123
|
|
980
|
+
```
|
|
981
|
+
The parent function can be suppressed by setting `show_line_number` or `sln` to `"n"` or `"no parent"`.
|
|
982
|
+
|
|
983
|
+
# Configuring at import time
|
|
984
|
+
|
|
985
|
+
It can be useful to configure peek at import time. This can be done by providing a `peek.json` file which
|
|
986
|
+
can contain any attribute configuration overriding the standard settings.
|
|
987
|
+
E.g. if there is an `peek.json` file with the following contents
|
|
988
|
+
|
|
989
|
+
```
|
|
990
|
+
{
|
|
991
|
+
"o": "stderr",
|
|
992
|
+
"show_time": true,
|
|
993
|
+
"line_length": 80`
|
|
994
|
+
'compact' : true
|
|
995
|
+
}
|
|
996
|
+
```
|
|
997
|
+
in the same folder as the application, this program:
|
|
998
|
+
```
|
|
999
|
+
hello = "world"
|
|
1000
|
+
peek(hello)
|
|
1001
|
+
```
|
|
1002
|
+
will print to stderr (rather than stdout):
|
|
1003
|
+
```
|
|
1004
|
+
@ 14:53:41.392190 ==> hello='world'
|
|
1005
|
+
```
|
|
1006
|
+
At import time the sys.path will be searched for, in that order, to find a `peek.json` file and use that. This means that
|
|
1007
|
+
you can place a `peek.json` file in the site-packages folder where `peek` is installed to always use
|
|
1008
|
+
these modified settings.
|
|
1009
|
+
|
|
1010
|
+
Please observe that json values are slightly different from their Python equivalents:
|
|
1011
|
+
```
|
|
1012
|
+
-------------------------------
|
|
1013
|
+
Python json
|
|
1014
|
+
-------------------------------
|
|
1015
|
+
True true
|
|
1016
|
+
False false
|
|
1017
|
+
None none
|
|
1018
|
+
strings always double quoted
|
|
1019
|
+
-------------------------------
|
|
1020
|
+
```
|
|
1021
|
+
Note that not-specified attributes will remain the default settings.
|
|
1022
|
+
|
|
1023
|
+
For obvious reasons, it is not possible to specify `serialize` in an peek.json file.
|
|
1024
|
+
|
|
1025
|
+
# Working with multiple instances of peek
|
|
1026
|
+
|
|
1027
|
+
Normally, only the `peek()` object is used.
|
|
1028
|
+
|
|
1029
|
+
It can be useful to have multiple instances, e.g. when some of the debugging has to be done with context information
|
|
1030
|
+
and others requires an alternative prefix.
|
|
1031
|
+
|
|
1032
|
+
THere are several ways to obtain a new instance of peek:
|
|
1033
|
+
|
|
1034
|
+
* by using `peek.new()`
|
|
1035
|
+
|
|
1036
|
+
With this a new peek object is created with the default attributes
|
|
1037
|
+
and possibly peek.json overrides.
|
|
1038
|
+
* by using `peek.new(ignore_json=True)`
|
|
1039
|
+
|
|
1040
|
+
With this a new peekobject is created with the default attibutes. Any peek.json files asre ignored.
|
|
1041
|
+
* by using `peek.fork()`
|
|
1042
|
+
|
|
1043
|
+
With this a new peek object is created with the same attributes as the object it is created ('the parent') from. Note that any non set attributes are copied (propagated) from the parent.
|
|
1044
|
+
* by using `peek.clone()`, which copies all attributes from peek()
|
|
1045
|
+
|
|
1046
|
+
With this a new peek object is created with the same attributes as the object it is created ('the parent') from. Note that the attributes are not propagated from the parent, in this case.
|
|
1047
|
+
|
|
1048
|
+
* with `peek()` used as a context manager
|
|
1049
|
+
|
|
1050
|
+
In either case, attributes can be added to override the default ones.
|
|
1051
|
+
|
|
1052
|
+
### Example
|
|
1053
|
+
```
|
|
1054
|
+
peek_with_line_number = peek.fork(show_line_number=True)
|
|
1055
|
+
peek_with_new_prefix = peek.new(prefix="==> ")
|
|
1056
|
+
peek_with_new_prefix_and_time = peek_with_new_prefix.clone(show_time=True)
|
|
1057
|
+
hello="world"
|
|
1058
|
+
peek_with_line_number(hello)
|
|
1059
|
+
peek_with_new_prefix(hello)
|
|
1060
|
+
peek_with_new_prefix_and_time(hello)
|
|
1061
|
+
peek.equals_separator = " == " # this affects only the forked objects
|
|
1062
|
+
peek_with_line_number(hello)
|
|
1063
|
+
peek_with_new_prefix(hello)
|
|
1064
|
+
peek_with_new_prefix_and_time(hello)
|
|
1065
|
+
with peek(prefix="peek_cm ") as peek_cm:
|
|
1066
|
+
peek_cm(hello)
|
|
1067
|
+
peek(hello)
|
|
1068
|
+
```
|
|
1069
|
+
prints something like
|
|
1070
|
+
```
|
|
1071
|
+
#28 ==> hello='world'
|
|
1072
|
+
==> hello='world'
|
|
1073
|
+
==> @ 09:55:52.122818 ==> hello='world'
|
|
1074
|
+
#32 ==> hello == 'world'
|
|
1075
|
+
==> hello='world'
|
|
1076
|
+
==> @ 09:55:52.125928 ==> hello='world'
|
|
1077
|
+
peek_cm enter
|
|
1078
|
+
peek_cm hello == 'world'
|
|
1079
|
+
hello == 'world'
|
|
1080
|
+
peek_cm exit in 0.001843 seconds
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
## ignore_json
|
|
1084
|
+
With `peek.new(ignore_json=True)` an instance of peek without having applied any json configuration file will be returned. That can be useful when guaranteeing the same output in several setups.
|
|
1085
|
+
|
|
1086
|
+
### Example
|
|
1087
|
+
Suppose we have a `peek.json` file in the current directory with the contents
|
|
1088
|
+
```
|
|
1089
|
+
{prefix="==>"}
|
|
1090
|
+
```
|
|
1091
|
+
Then
|
|
1092
|
+
```
|
|
1093
|
+
peek_post_json = peek.new()
|
|
1094
|
+
peek_ignore_json = peek.new(ignore_json=True)
|
|
1095
|
+
hello = "world"
|
|
1096
|
+
peek(hello)
|
|
1097
|
+
peek_post_json(hello)
|
|
1098
|
+
peek_ignore_json(hello)
|
|
1099
|
+
```
|
|
1100
|
+
prints
|
|
1101
|
+
```
|
|
1102
|
+
==>hello='world'
|
|
1103
|
+
==>hello='world'
|
|
1104
|
+
hello='world'
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
# Test script
|
|
1108
|
+
|
|
1109
|
+
On GitHub is a file `test_peek.py` that tests (and thus also demonstrates) most of the functionality
|
|
1110
|
+
of peek.
|
|
1111
|
+
|
|
1112
|
+
It is very useful to have a look at the tests to see the features (some may be not covered (yet) in this readme).
|
|
1113
|
+
|
|
1114
|
+
# Using peek in a REPL
|
|
1115
|
+
|
|
1116
|
+
Peek may be used in a REPL, but with limited functionality:
|
|
1117
|
+
* all arguments are just presented as such, i.e. no left-hand side, e.g.
|
|
1118
|
+
```
|
|
1119
|
+
>> hello = "world"
|
|
1120
|
+
>>> peek(hello, hello * 2)
|
|
1121
|
+
'hello', 'hellohello'
|
|
1122
|
+
('hello', 'hellohello')
|
|
1123
|
+
```
|
|
1124
|
+
* line numbers are never shown
|
|
1125
|
+
* use as a decorator is not supported
|
|
1126
|
+
* use as a context manager is not supported
|
|
1127
|
+
|
|
1128
|
+
# Alternative to `peek`
|
|
1129
|
+
|
|
1130
|
+
Sometimes, even peek is too long during a debug session or it is not suitable to use the name peek.
|
|
1131
|
+
|
|
1132
|
+
In that case, it is possible to use p instead
|
|
1133
|
+
```
|
|
1134
|
+
from peek import p
|
|
1135
|
+
```
|
|
1136
|
+
The `p` object is a *fork* of peek. That means that attributes of `peek` are propagated to `p`, unless overridden.
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
# Limitations
|
|
1140
|
+
|
|
1141
|
+
It is not possible to use peek:
|
|
1142
|
+
* from a frozen application (e.g. packaged with PyInstaller)
|
|
1143
|
+
* when the underlying source code has changed during execution
|
|
1144
|
+
|
|
1145
|
+
# Implementation details
|
|
1146
|
+
|
|
1147
|
+
Although not important for using the package, here are some implementation details:
|
|
1148
|
+
* peek.py contains the complete source of the asttokens, executing and six packages, in
|
|
1149
|
+
order to offer the required source lookups, without any dependencies
|
|
1150
|
+
* in order to support using peek() as a decorator and a context manager, peek caches the complete source of
|
|
1151
|
+
any source file that uses peek()
|
|
1152
|
+
|
|
1153
|
+
# Changelog
|
|
1154
|
+
|
|
1155
|
+
The changelog can be found here:
|
|
1156
|
+
|
|
1157
|
+
* https://github.com/salabim/peek/main/changelog.md or
|
|
1158
|
+
* https://salabim.org/peek/changelog.html
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
# Acknowledgement
|
|
1162
|
+
|
|
1163
|
+
The **peek** package is inspired by the **IceCream** package, but is a
|
|
1164
|
+
nearly complete rewrite. See https://github.com/gruns/icecream
|
|
1165
|
+
|
|
1166
|
+
Many thanks to the author Ansgar Grunseid / grunseid.com / grunseid@gmail.com .
|
|
1167
|
+
|
|
1168
|
+
The peek package is a rebrand of the **ycecream** package, with enhancements.
|
|
1169
|
+
|
|
1170
|
+
# Differences with IceCream
|
|
1171
|
+
|
|
1172
|
+
The peek module was originally a fork of **IceCream**, but has many differences:
|
|
1173
|
+
|
|
1174
|
+
```
|
|
1175
|
+
-------------------------------------------------------------------------------------------
|
|
1176
|
+
characteristic peek IceCream
|
|
1177
|
+
-------------------------------------------------------------------------------------------
|
|
1178
|
+
default name peek ic
|
|
1179
|
+
import method import peek from icecream import ic
|
|
1180
|
+
dependencies none many
|
|
1181
|
+
number of files 1 several
|
|
1182
|
+
usable without installation yes no
|
|
1183
|
+
can be used as a decorator yes no
|
|
1184
|
+
can be used as a context manager yes no
|
|
1185
|
+
can show traceback yes no
|
|
1186
|
+
PEP8 (Pythonic) API yes no
|
|
1187
|
+
sorts dicts no by default, optional *) yes
|
|
1188
|
+
supports compact, indent,
|
|
1189
|
+
and underscore_numbers
|
|
1190
|
+
parameters of pprint yes **) no
|
|
1191
|
+
use from a REPL limited functionality no
|
|
1192
|
+
external configuration via json file no
|
|
1193
|
+
observes line_length correctly yes no
|
|
1194
|
+
default line length 160 80
|
|
1195
|
+
benchmarking functionality yes no
|
|
1196
|
+
suppress f-strings at left hand optional no
|
|
1197
|
+
indentation 4 blanks (overridable) dependent on length of prefix
|
|
1198
|
+
forking and cloning yes no
|
|
1199
|
+
test script pytest unittest
|
|
1200
|
+
colourize no yes (can be disabled)
|
|
1201
|
+
-------------------------------------------------------------------------------------------
|
|
1202
|
+
*) under Python <= 3.7, dicts are always sorted (regardless of the sort_dicts attribute
|
|
1203
|
+
**) under Python <= 3.7, numbers are never underscored (regardless of the underscore_numnbers attribute
|
|
1204
|
+
|
|
1205
|
+
|
|
1206
|
+
```
|
|
1207
|
+
  
|
|
1208
|
+
|
|
1209
|
+
 
|
|
1210
|
+

|
|
1211
|
+
|