summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Simionato <michele.simionato@gmail.com>2015-07-22 07:32:49 +0200
committerMichele Simionato <michele.simionato@gmail.com>2015-07-22 07:32:49 +0200
commit4b28eea14c0ab65e447cf2955c26bc9a8e5fd11b (patch)
tree3aabc01ff7a68063519ef60e33a23116177b6068
parent10e035eaf93997a63a30687f6fe33b918714ba61 (diff)
downloadpython-decorator-git-4b28eea14c0ab65e447cf2955c26bc9a8e5fd11b.tar.gz
Refined the virtual ancestors management and the tests
-rw-r--r--.travis.yml2
-rw-r--r--documentation.pdf2500
-rw-r--r--documentation.rst154
-rw-r--r--src/decorator.py31
-rw-r--r--src/tests/documentation.py152
-rw-r--r--src/tests/test.py111
6 files changed, 1646 insertions, 1304 deletions
diff --git a/.travis.yml b/.travis.yml
index 981d9e0..55a4f81 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,4 +12,4 @@ install:
- python setup.py install
script:
- python test.py -v
+ python src/tests/test.py -v
diff --git a/documentation.pdf b/documentation.pdf
index b4e28f8..802956a 100644
--- a/documentation.pdf
+++ b/documentation.pdf
@@ -1,7 +1,7 @@
%PDF-1.4
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
-<< /F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 47 0 R /F5 51 0 R /F6 52 0 R >>
+<< /F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 50 0 R /F5 53 0 R /F6 54 0 R >>
endobj
2 0 obj
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
@@ -19,294 +19,307 @@ endobj
<< /A << /S /URI /Type /Action /URI (http://pypi.python.org/pypi/decorator/4.0.0) >> /Border [ 0 0 0 ] /Rect [ 153.7323 659.7736 338.2823 671.7736 ] /Subtype /Link /Type /Annot >>
endobj
7 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 48 0 R /XYZ 62.69291 239.0236 0 ] /Rect [ 62.69291 560.0236 155.4829 572.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 51 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 62.69291 560.0236 121.0229 572.0236 ] /Subtype /Link /Type /Annot >>
endobj
8 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 48 0 R /XYZ 62.69291 239.0236 0 ] /Rect [ 527.0227 560.7736 532.5827 572.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 51 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 527.0227 560.7736 532.5827 572.7736 ] /Subtype /Link /Type /Annot >>
endobj
9 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 49 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 62.69291 542.0236 117.3029 554.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 51 0 R /XYZ 62.69291 594.0236 0 ] /Rect [ 62.69291 542.0236 117.3029 554.0236 ] /Subtype /Link /Type /Annot >>
endobj
10 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 49 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 527.0227 542.7736 532.5827 554.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 51 0 R /XYZ 62.69291 594.0236 0 ] /Rect [ 527.0227 542.7736 532.5827 554.7736 ] /Subtype /Link /Type /Annot >>
endobj
11 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 49 0 R /XYZ 62.69291 564.0236 0 ] /Rect [ 62.69291 524.0236 182.7229 536.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 51 0 R /XYZ 62.69291 381.0236 0 ] /Rect [ 62.69291 524.0236 182.7229 536.0236 ] /Subtype /Link /Type /Annot >>
endobj
12 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 49 0 R /XYZ 62.69291 564.0236 0 ] /Rect [ 527.0227 524.7736 532.5827 536.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 51 0 R /XYZ 62.69291 381.0236 0 ] /Rect [ 527.0227 524.7736 532.5827 536.7736 ] /Subtype /Link /Type /Annot >>
endobj
13 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 49 0 R /XYZ 62.69291 267.0236 0 ] /Rect [ 62.69291 506.0236 114.3629 518.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 56 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 62.69291 506.0236 114.3629 518.0236 ] /Subtype /Link /Type /Annot >>
endobj
14 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 49 0 R /XYZ 62.69291 267.0236 0 ] /Rect [ 527.0227 506.7736 532.5827 518.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 56 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 527.0227 506.7736 532.5827 518.7736 ] /Subtype /Link /Type /Annot >>
endobj
15 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 54 0 R /XYZ 62.69291 699.0236 0 ] /Rect [ 62.69291 488.0236 183.2629 500.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 56 0 R /XYZ 62.69291 528.0236 0 ] /Rect [ 62.69291 488.0236 183.2629 500.0236 ] /Subtype /Link /Type /Annot >>
endobj
16 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 54 0 R /XYZ 62.69291 699.0236 0 ] /Rect [ 527.0227 488.7736 532.5827 500.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 56 0 R /XYZ 62.69291 528.0236 0 ] /Rect [ 527.0227 488.7736 532.5827 500.7736 ] /Subtype /Link /Type /Annot >>
endobj
17 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 55 0 R /XYZ 62.69291 659.8236 0 ] /Rect [ 62.69291 470.0236 122.1429 482.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 57 0 R /XYZ 62.69291 469.4236 0 ] /Rect [ 62.69291 470.0236 122.1429 482.0236 ] /Subtype /Link /Type /Annot >>
endobj
18 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 55 0 R /XYZ 62.69291 659.8236 0 ] /Rect [ 527.0227 470.7736 532.5827 482.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 57 0 R /XYZ 62.69291 469.4236 0 ] /Rect [ 527.0227 470.7736 532.5827 482.7736 ] /Subtype /Link /Type /Annot >>
endobj
19 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 57 0 R /XYZ 62.69291 715.8236 0 ] /Rect [ 62.69291 452.0236 69.91291 464.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 58 0 R /XYZ 62.69291 492.6236 0 ] /Rect [ 62.69291 452.0236 69.91291 464.0236 ] /Subtype /Link /Type /Annot >>
endobj
20 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 57 0 R /XYZ 62.69291 715.8236 0 ] /Rect [ 72.69291 452.0236 102.6929 464.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 58 0 R /XYZ 62.69291 492.6236 0 ] /Rect [ 72.69291 452.0236 102.6929 464.0236 ] /Subtype /Link /Type /Annot >>
endobj
21 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 57 0 R /XYZ 62.69291 715.8236 0 ] /Rect [ 108.6929 452.0236 154.8129 464.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 58 0 R /XYZ 62.69291 492.6236 0 ] /Rect [ 108.6929 452.0236 154.8129 464.0236 ] /Subtype /Link /Type /Annot >>
endobj
22 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 57 0 R /XYZ 62.69291 715.8236 0 ] /Rect [ 527.0227 452.7736 532.5827 464.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 58 0 R /XYZ 62.69291 492.6236 0 ] /Rect [ 527.0227 452.7736 532.5827 464.7736 ] /Subtype /Link /Type /Annot >>
endobj
23 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 57 0 R /XYZ 62.69291 181.6236 0 ] /Rect [ 62.69291 434.0236 164.3629 446.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 60 0 R /XYZ 62.69291 631.8236 0 ] /Rect [ 62.69291 434.0236 164.3629 446.0236 ] /Subtype /Link /Type /Annot >>
endobj
24 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 57 0 R /XYZ 62.69291 181.6236 0 ] /Rect [ 527.0227 434.7736 532.5827 446.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 60 0 R /XYZ 62.69291 631.8236 0 ] /Rect [ 527.0227 434.7736 532.5827 446.7736 ] /Subtype /Link /Type /Annot >>
endobj
25 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 58 0 R /XYZ 62.69291 361.4236 0 ] /Rect [ 62.69291 416.0236 176.6929 428.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 61 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 62.69291 416.0236 176.6929 428.0236 ] /Subtype /Link /Type /Annot >>
endobj
26 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 58 0 R /XYZ 62.69291 361.4236 0 ] /Rect [ 527.0227 416.7736 532.5827 428.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 61 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 527.0227 416.7736 532.5827 428.7736 ] /Subtype /Link /Type /Annot >>
endobj
27 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 59 0 R /XYZ 62.69291 594.6236 0 ] /Rect [ 62.69291 398.0236 110.6929 410.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 61 0 R /XYZ 62.69291 317.2236 0 ] /Rect [ 62.69291 398.0236 110.6929 410.0236 ] /Subtype /Link /Type /Annot >>
endobj
28 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 59 0 R /XYZ 62.69291 594.6236 0 ] /Rect [ 527.0227 398.7736 532.5827 410.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 61 0 R /XYZ 62.69291 317.2236 0 ] /Rect [ 527.0227 398.7736 532.5827 410.7736 ] /Subtype /Link /Type /Annot >>
endobj
29 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 60 0 R /XYZ 62.69291 715.8236 0 ] /Rect [ 62.69291 380.0236 146.6929 392.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 62 0 R /XYZ 62.69291 434.6236 0 ] /Rect [ 62.69291 380.0236 146.6929 392.0236 ] /Subtype /Link /Type /Annot >>
endobj
30 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 60 0 R /XYZ 62.69291 715.8236 0 ] /Rect [ 527.0227 380.7736 532.5827 392.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 62 0 R /XYZ 62.69291 434.6236 0 ] /Rect [ 527.0227 380.7736 532.5827 392.7736 ] /Subtype /Link /Type /Annot >>
endobj
31 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 60 0 R /XYZ 62.69291 164.4236 0 ] /Rect [ 62.69291 362.0236 139.9329 374.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 63 0 R /XYZ 62.69291 542.6236 0 ] /Rect [ 62.69291 362.0236 139.9329 374.0236 ] /Subtype /Link /Type /Annot >>
endobj
32 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 60 0 R /XYZ 62.69291 164.4236 0 ] /Rect [ 527.0227 362.7736 532.5827 374.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 63 0 R /XYZ 62.69291 542.6236 0 ] /Rect [ 527.0227 362.7736 532.5827 374.7736 ] /Subtype /Link /Type /Annot >>
endobj
33 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 61 0 R /XYZ 62.69291 265.4236 0 ] /Rect [ 62.69291 344.0236 80.47291 356.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 64 0 R /XYZ 62.69291 669.0236 0 ] /Rect [ 62.69291 344.0236 80.47291 356.0236 ] /Subtype /Link /Type /Annot >>
endobj
34 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 61 0 R /XYZ 62.69291 265.4236 0 ] /Rect [ 83.25291 344.0236 161.2529 356.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 64 0 R /XYZ 62.69291 669.0236 0 ] /Rect [ 83.25291 344.0236 161.2529 356.0236 ] /Subtype /Link /Type /Annot >>
endobj
35 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 61 0 R /XYZ 62.69291 265.4236 0 ] /Rect [ 167.2529 344.0236 192.2729 356.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 64 0 R /XYZ 62.69291 669.0236 0 ] /Rect [ 167.2529 344.0236 192.2729 356.0236 ] /Subtype /Link /Type /Annot >>
endobj
36 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 61 0 R /XYZ 62.69291 265.4236 0 ] /Rect [ 527.0227 344.7736 532.5827 356.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 64 0 R /XYZ 62.69291 669.0236 0 ] /Rect [ 521.4627 344.7736 532.5827 356.7736 ] /Subtype /Link /Type /Annot >>
endobj
37 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 62 0 R /XYZ 62.69291 354.6236 0 ] /Rect [ 62.69291 326.0236 177.1629 338.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 66 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 62.69291 326.0236 177.1629 338.0236 ] /Subtype /Link /Type /Annot >>
endobj
38 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 62 0 R /XYZ 62.69291 354.6236 0 ] /Rect [ 521.4627 326.7736 532.5827 338.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 66 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 521.4627 326.7736 532.5827 338.7736 ] /Subtype /Link /Type /Annot >>
endobj
39 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 65 0 R /XYZ 62.69291 542.6236 0 ] /Rect [ 62.69291 308.0236 228.2829 320.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 66 0 R /XYZ 62.69291 285.2236 0 ] /Rect [ 62.69291 308.0236 228.2829 320.0236 ] /Subtype /Link /Type /Annot >>
endobj
40 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 65 0 R /XYZ 62.69291 542.6236 0 ] /Rect [ 521.4627 308.7736 532.5827 320.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 66 0 R /XYZ 62.69291 285.2236 0 ] /Rect [ 521.4627 308.7736 532.5827 320.7736 ] /Subtype /Link /Type /Annot >>
endobj
41 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 67 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 62.69291 290.0236 144.3729 302.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 69 0 R /XYZ 62.69291 558.6236 0 ] /Rect [ 62.69291 290.0236 144.3729 302.0236 ] /Subtype /Link /Type /Annot >>
endobj
42 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 67 0 R /XYZ 62.69291 765.0236 0 ] /Rect [ 521.4627 290.7736 532.5827 302.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 69 0 R /XYZ 62.69291 558.6236 0 ] /Rect [ 521.4627 290.7736 532.5827 302.7736 ] /Subtype /Link /Type /Annot >>
endobj
43 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 69 0 R /XYZ 62.69291 333.0236 0 ] /Rect [ 62.69291 272.0236 174.3929 284.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 71 0 R /XYZ 62.69291 607.8236 0 ] /Rect [ 62.69291 272.0236 236.6529 284.0236 ] /Subtype /Link /Type /Annot >>
endobj
44 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 69 0 R /XYZ 62.69291 333.0236 0 ] /Rect [ 521.4627 272.7736 532.5827 284.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 71 0 R /XYZ 62.69291 607.8236 0 ] /Rect [ 521.4627 272.7736 532.5827 284.7736 ] /Subtype /Link /Type /Annot >>
endobj
45 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 72 0 R /XYZ 62.69291 494.6236 0 ] /Rect [ 62.69291 254.0236 106.0329 266.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 72 0 R /XYZ 62.69291 499.4236 0 ] /Rect [ 62.69291 254.0236 174.3929 266.0236 ] /Subtype /Link /Type /Annot >>
endobj
46 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 72 0 R /XYZ 62.69291 494.6236 0 ] /Rect [ 521.4627 254.7736 532.5827 266.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 72 0 R /XYZ 62.69291 499.4236 0 ] /Rect [ 521.4627 254.7736 532.5827 266.7736 ] /Subtype /Link /Type /Annot >>
endobj
47 0 obj
-<< /BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 655.8236 0 ] /Rect [ 62.69291 236.0236 106.0329 248.0236 ] /Subtype /Link /Type /Annot >>
endobj
48 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 655.8236 0 ] /Rect [ 521.4627 236.7736 532.5827 248.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+49 0 obj
<< /Annots [ 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R
15 0 R 16 0 R 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R
25 0 R 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R
35 0 R 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R
- 45 0 R 46 0 R ] /Contents 95 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ 45 0 R 46 0 R 47 0 R 48 0 R ] /Contents 99 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
/Trans << >> /Type /Page >>
endobj
-49 0 obj
-<< /Contents 96 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
- /Type /Page >>
-endobj
50 0 obj
-<< /A << /S /URI /Type /Action /URI (http://www.python.org/moin/PythonDecoratorLibrary) >> /Border [ 0 0 0 ] /Rect [ 219.6428 624.0236 449.1728 636.0236 ] /Subtype /Link /Type /Annot >>
+<< /BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font >>
endobj
51 0 obj
-<< /BaseFont /Courier-Bold /Encoding /WinAnsiEncoding /Name /F5 /Subtype /Type1 /Type /Font >>
+<< /Contents 100 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
endobj
52 0 obj
-<< /BaseFont /Courier-Oblique /Encoding /WinAnsiEncoding /Name /F6 /Subtype /Type1 /Type /Font >>
+<< /A << /S /URI /Type /Action /URI (http://www.python.org/moin/PythonDecoratorLibrary) >> /Border [ 0 0 0 ] /Rect [ 219.6428 453.0236 449.1728 465.0236 ] /Subtype /Link /Type /Annot >>
endobj
53 0 obj
-<< /A << /S /URI /Type /Action /URI (https://docs.python.org/3/library/functools.html#functools.update_wrapper) >> /Border [ 0 0 0 ] /Rect [ 151.0486 414.8236 267.91 426.8236 ] /Subtype /Link /Type /Annot >>
+<< /BaseFont /Courier-Bold /Encoding /WinAnsiEncoding /Name /F5 /Subtype /Type1 /Type /Font >>
endobj
54 0 obj
-<< /Annots [ 50 0 R 53 0 R ] /Contents 97 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
- /Trans << >> /Type /Page >>
+<< /BaseFont /Courier-Oblique /Encoding /WinAnsiEncoding /Name /F6 /Subtype /Type1 /Type /Font >>
endobj
55 0 obj
-<< /Contents 98 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
- /Type /Page >>
+<< /A << /S /URI /Type /Action /URI (https://docs.python.org/3/library/functools.html#functools.update_wrapper) >> /Border [ 0 0 0 ] /Rect [ 151.0486 243.8236 267.91 255.8236 ] /Subtype /Link /Type /Annot >>
endobj
56 0 obj
-<< /A << /S /URI /Type /Action /URI (http://www.python.org/dev/peps/pep-3107/) >> /Border [ 0 0 0 ] /Rect [ 231.6368 142.6236 323.0741 154.6236 ] /Subtype /Link /Type /Annot >>
+<< /Annots [ 52 0 R 55 0 R ] /Contents 101 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
endobj
57 0 obj
-<< /Annots [ 56 0 R ] /Contents 99 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
- /Trans << >> /Type /Page >>
+<< /Contents 102 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
endobj
58 0 obj
-<< /Contents 100 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 103 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
59 0 obj
-<< /Contents 101 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
- /Type /Page >>
+<< /A << /S /URI /Type /Action /URI (http://www.python.org/dev/peps/pep-3107/) >> /Border [ 0 0 0 ] /Rect [ 231.6368 592.8236 323.0741 604.8236 ] /Subtype /Link /Type /Annot >>
endobj
60 0 obj
-<< /Contents 102 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
- /Type /Page >>
+<< /Annots [ 59 0 R ] /Contents 104 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
endobj
61 0 obj
-<< /Contents 103 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 105 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
62 0 obj
-<< /Contents 104 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 106 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
63 0 obj
-<< /A << /S /URI /Type /Action /URI (http://bugs.python.org/issue1764286) >> /Border [ 0 0 0 ] /Rect [ 137.6966 707.8236 178.0879 719.8236 ] /Subtype /Link /Type /Annot >>
+<< /Contents 107 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
endobj
64 0 obj
-<< /A << /S /URI /Type /Action /URI (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496691) >> /Border [ 0 0 0 ] /Rect [ 62.69291 222.4236 363.4029 234.4236 ] /Subtype /Link /Type /Annot >>
+<< /Contents 108 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
endobj
65 0 obj
-<< /Annots [ 63 0 R 64 0 R ] /Contents 105 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
- /Trans << >> /Type /Page >>
+<< /A << /S /URI /Type /Action /URI (http://bugs.python.org/issue1764286) >> /Border [ 0 0 0 ] /Rect [ 133.3162 450.4236 172.2473 462.4236 ] /Subtype /Link /Type /Annot >>
endobj
66 0 obj
-<< /Contents 106 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
- /Type /Page >>
+<< /Annots [ 65 0 R ] /Contents 109 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
endobj
67 0 obj
-<< /Contents 107 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
- /Type /Page >>
+<< /A << /S /URI /Type /Action /URI (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496691) >> /Border [ 0 0 0 ] /Rect [ 62.69291 645.0236 363.4029 657.0236 ] /Subtype /Link /Type /Annot >>
endobj
68 0 obj
-<< /Contents 108 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
- /Type /Page >>
+<< /Annots [ 67 0 R ] /Contents 110 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
endobj
69 0 obj
-<< /Contents 109 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 111 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
70 0 obj
-<< /A << /S /URI /Type /Action /URI (http://www.python.org/dev/peps/pep-0362) >> /Border [ 0 0 0 ] /Rect [ 301.1597 248.2236 317.8397 260.2236 ] /Subtype /Link /Type /Annot >>
+<< /Contents 112 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
endobj
71 0 obj
-<< /Annots [ 70 0 R ] /Contents 110 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
- /Trans << >> /Type /Page >>
+<< /Contents 113 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
endobj
72 0 obj
-<< /Contents 111 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 94 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 114 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
73 0 obj
-<< /Outlines 75 0 R /PageLabels 112 0 R /PageMode /UseNone /Pages 94 0 R /Type /Catalog >>
+<< /A << /S /URI /Type /Action /URI (http://www.python.org/dev/peps/pep-0362) >> /Border [ 0 0 0 ] /Rect [ 301.1597 412.6236 317.8397 424.6236 ] /Subtype /Link /Type /Annot >>
endobj
74 0 obj
-<< /Author (Michele Simionato) /CreationDate (D:20150721164151-01'00') /Creator (\(unspecified\)) /Keywords () /Producer (ReportLab PDF Library - www.reportlab.com) /Subject (\(unspecified\))
- /Title (The decorator module) >>
+<< /Annots [ 73 0 R ] /Contents 115 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
endobj
75 0 obj
-<< /Count 18 /First 76 0 R /Last 93 0 R /Type /Outlines >>
+<< /Contents 116 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 98 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
endobj
76 0 obj
-<< /Dest [ 48 0 R /XYZ 62.69291 239.0236 0 ] /Next 77 0 R /Parent 75 0 R /Title (Compatibility notes) >>
+<< /Outlines 78 0 R /PageLabels 117 0 R /PageMode /UseNone /Pages 98 0 R /Type /Catalog >>
endobj
77 0 obj
-<< /Dest [ 49 0 R /XYZ 62.69291 765.0236 0 ] /Next 78 0 R /Parent 75 0 R /Prev 76 0 R /Title (What's new) >>
+<< /Author (Michele Simionato) /CreationDate (D:20150722073225-01'00') /Creator (\(unspecified\)) /Keywords () /Producer (ReportLab PDF Library - www.reportlab.com) /Subject (\(unspecified\))
+ /Title (The decorator module) >>
endobj
78 0 obj
-<< /Dest [ 49 0 R /XYZ 62.69291 564.0236 0 ] /Next 79 0 R /Parent 75 0 R /Prev 77 0 R /Title (Usefulness of decorators) >>
+<< /Count 19 /First 79 0 R /Last 97 0 R /Type /Outlines >>
endobj
79 0 obj
-<< /Dest [ 49 0 R /XYZ 62.69291 267.0236 0 ] /Next 80 0 R /Parent 75 0 R /Prev 78 0 R /Title (Definitions) >>
+<< /Dest [ 51 0 R /XYZ 62.69291 765.0236 0 ] /Next 80 0 R /Parent 78 0 R /Title (Introduction) >>
endobj
80 0 obj
-<< /Dest [ 54 0 R /XYZ 62.69291 699.0236 0 ] /Next 81 0 R /Parent 75 0 R /Prev 79 0 R /Title (Statement of the problem) >>
+<< /Dest [ 51 0 R /XYZ 62.69291 594.0236 0 ] /Next 81 0 R /Parent 78 0 R /Prev 79 0 R /Title (What's new) >>
endobj
81 0 obj
-<< /Dest [ 55 0 R /XYZ 62.69291 659.8236 0 ] /Next 82 0 R /Parent 75 0 R /Prev 80 0 R /Title (The solution) >>
+<< /Dest [ 51 0 R /XYZ 62.69291 381.0236 0 ] /Next 82 0 R /Parent 78 0 R /Prev 80 0 R /Title (Usefulness of decorators) >>
endobj
82 0 obj
-<< /Dest [ 57 0 R /XYZ 62.69291 715.8236 0 ] /Next 83 0 R /Parent 75 0 R /Prev 81 0 R /Title (A trace decorator) >>
+<< /Dest [ 56 0 R /XYZ 62.69291 765.0236 0 ] /Next 83 0 R /Parent 78 0 R /Prev 81 0 R /Title (Definitions) >>
endobj
83 0 obj
-<< /Dest [ 57 0 R /XYZ 62.69291 181.6236 0 ] /Next 84 0 R /Parent 75 0 R /Prev 82 0 R /Title (Function annotations) >>
+<< /Dest [ 56 0 R /XYZ 62.69291 528.0236 0 ] /Next 84 0 R /Parent 78 0 R /Prev 82 0 R /Title (Statement of the problem) >>
endobj
84 0 obj
-<< /Dest [ 58 0 R /XYZ 62.69291 361.4236 0 ] /Next 85 0 R /Parent 75 0 R /Prev 83 0 R /Title (decorator.decorator) >>
+<< /Dest [ 57 0 R /XYZ 62.69291 469.4236 0 ] /Next 85 0 R /Parent 78 0 R /Prev 83 0 R /Title (The solution) >>
endobj
85 0 obj
-<< /Dest [ 59 0 R /XYZ 62.69291 594.6236 0 ] /Next 86 0 R /Parent 75 0 R /Prev 84 0 R /Title (blocking) >>
+<< /Dest [ 58 0 R /XYZ 62.69291 492.6236 0 ] /Next 86 0 R /Parent 78 0 R /Prev 84 0 R /Title (A trace decorator) >>
endobj
86 0 obj
-<< /Dest [ 60 0 R /XYZ 62.69291 715.8236 0 ] /Next 87 0 R /Parent 75 0 R /Prev 85 0 R /Title (decorator\(cls\)) >>
+<< /Dest [ 60 0 R /XYZ 62.69291 631.8236 0 ] /Next 87 0 R /Parent 78 0 R /Prev 85 0 R /Title (Function annotations) >>
endobj
87 0 obj
-<< /Dest [ 60 0 R /XYZ 62.69291 164.4236 0 ] /Next 88 0 R /Parent 75 0 R /Prev 86 0 R /Title (contextmanager) >>
+<< /Dest [ 61 0 R /XYZ 62.69291 765.0236 0 ] /Next 88 0 R /Parent 78 0 R /Prev 86 0 R /Title (decorator.decorator) >>
endobj
88 0 obj
-<< /Dest [ 61 0 R /XYZ 62.69291 265.4236 0 ] /Next 89 0 R /Parent 75 0 R /Prev 87 0 R /Title (The FunctionMaker class) >>
+<< /Dest [ 61 0 R /XYZ 62.69291 317.2236 0 ] /Next 89 0 R /Parent 78 0 R /Prev 87 0 R /Title (blocking) >>
endobj
89 0 obj
-<< /Dest [ 62 0 R /XYZ 62.69291 354.6236 0 ] /Next 90 0 R /Parent 75 0 R /Prev 88 0 R /Title (Getting the source code) >>
+<< /Dest [ 62 0 R /XYZ 62.69291 434.6236 0 ] /Next 90 0 R /Parent 78 0 R /Prev 88 0 R /Title (decorator\(cls\)) >>
endobj
90 0 obj
-<< /Dest [ 65 0 R /XYZ 62.69291 542.6236 0 ] /Next 91 0 R /Parent 75 0 R /Prev 89 0 R /Title (Dealing with third party decorators) >>
+<< /Dest [ 63 0 R /XYZ 62.69291 542.6236 0 ] /Next 91 0 R /Parent 78 0 R /Prev 89 0 R /Title (contextmanager) >>
endobj
91 0 obj
-<< /Dest [ 67 0 R /XYZ 62.69291 765.0236 0 ] /Next 92 0 R /Parent 75 0 R /Prev 90 0 R /Title (Multiple dispatch) >>
+<< /Dest [ 64 0 R /XYZ 62.69291 669.0236 0 ] /Next 92 0 R /Parent 78 0 R /Prev 90 0 R /Title (The FunctionMaker class) >>
endobj
92 0 obj
-<< /Dest [ 69 0 R /XYZ 62.69291 333.0236 0 ] /Next 93 0 R /Parent 75 0 R /Prev 91 0 R /Title (Caveats and limitations) >>
+<< /Dest [ 66 0 R /XYZ 62.69291 765.0236 0 ] /Next 93 0 R /Parent 78 0 R /Prev 91 0 R /Title (Getting the source code) >>
endobj
93 0 obj
-<< /Dest [ 72 0 R /XYZ 62.69291 494.6236 0 ] /Parent 75 0 R /Prev 92 0 R /Title (LICENSE) >>
+<< /Dest [ 66 0 R /XYZ 62.69291 285.2236 0 ] /Next 94 0 R /Parent 78 0 R /Prev 92 0 R /Title (Dealing with third party decorators) >>
endobj
94 0 obj
-<< /Count 17 /Kids [ 48 0 R 49 0 R 54 0 R 55 0 R 57 0 R 58 0 R 59 0 R 60 0 R 61 0 R 62 0 R
- 65 0 R 66 0 R 67 0 R 68 0 R 69 0 R 71 0 R 72 0 R ] /Type /Pages >>
+<< /Dest [ 69 0 R /XYZ 62.69291 558.6236 0 ] /Next 95 0 R /Parent 78 0 R /Prev 93 0 R /Title (Multiple dispatch) >>
endobj
95 0 obj
-<< /Length 8676 >>
+<< /Dest [ 71 0 R /XYZ 62.69291 607.8236 0 ] /Next 96 0 R /Parent 78 0 R /Prev 94 0 R /Title (Generics and Abstract Base Classes) >>
+endobj
+96 0 obj
+<< /Dest [ 72 0 R /XYZ 62.69291 499.4236 0 ] /Next 97 0 R /Parent 78 0 R /Prev 95 0 R /Title (Caveats and limitations) >>
+endobj
+97 0 obj
+<< /Dest [ 75 0 R /XYZ 62.69291 655.8236 0 ] /Parent 78 0 R /Prev 96 0 R /Title (LICENSE) >>
+endobj
+98 0 obj
+<< /Count 18 /Kids [ 49 0 R 51 0 R 56 0 R 57 0 R 58 0 R 60 0 R 61 0 R 62 0 R 63 0 R 64 0 R
+ 66 0 R 68 0 R 69 0 R 70 0 R 71 0 R 72 0 R 74 0 R 75 0 R ] /Type /Pages >>
+endobj
+99 0 obj
+<< /Length 7558 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -371,7 +384,7 @@ q
1 0 0 1 91.03937 3 cm
q
0 0 0 rg
-BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (4.0.0 \(2015-07-21\)) Tj T* ET
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (4.0.0 \(2015-07-22\)) Tj T* ET
Q
Q
q
@@ -468,13 +481,27 @@ BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Contents) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 251.0236 cm
+1 0 0 1 62.69291 233.0236 cm
0 0 0 rg
BT /F1 10 Tf 12 TL ET
q
+1 0 0 1 0 327 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Introduction) Tj T* ET
+Q
+Q
+q
+1 0 0 1 397.8898 327 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
+Q
+Q
+q
1 0 0 1 0 309 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Compatibility notes) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (What's new) Tj T* ET
Q
Q
q
@@ -482,13 +509,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (1) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 291 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (What's new) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Usefulness of decorators) Tj T* ET
Q
Q
q
@@ -502,7 +529,7 @@ Q
q
1 0 0 1 0 273 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Usefulness of decorators) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Definitions) Tj T* ET
Q
Q
q
@@ -510,13 +537,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (3) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 255 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Definitions) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Statement of the problem) Tj T* ET
Q
Q
q
@@ -524,13 +551,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (2) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (3) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 237 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Statement of the problem) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (The solution) Tj T* ET
Q
Q
q
@@ -538,13 +565,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (3) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (4) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 219 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (The solution) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (A ) Tj /F3 10 Tf 0 0 0 rg (trace ) Tj /F2 10 Tf 0 0 .501961 rg (decorator) Tj T* ET
Q
Q
q
@@ -552,13 +579,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (4) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (5) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 201 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (A ) Tj /F3 10 Tf 0 0 0 rg (trace ) Tj /F2 10 Tf 0 0 .501961 rg (decorator) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Function annotations) Tj T* ET
Q
Q
q
@@ -566,13 +593,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (5) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (6) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 183 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Function annotations) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (decorator.decorator) Tj T* ET
Q
Q
q
@@ -580,13 +607,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (5) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (7) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 165 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (decorator.decorator) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (blocking) Tj T* ET
Q
Q
q
@@ -594,13 +621,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (6) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (7) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 147 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (blocking) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (decorator\(cls\)) Tj T* ET
Q
Q
q
@@ -608,13 +635,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (7) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (8) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 129 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (decorator\(cls\)) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (contextmanager) Tj T* ET
Q
Q
q
@@ -622,13 +649,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (8) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (9) Tj T* -66.44 0 Td ET
Q
Q
q
1 0 0 1 0 111 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (contextmanager) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (The ) Tj /F3 10 Tf 0 0 0 rg (FunctionMaker ) Tj /F2 10 Tf 0 0 .501961 rg (class) Tj T* ET
Q
Q
q
@@ -636,13 +663,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (8) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (10) Tj T* -60.88 0 Td ET
Q
Q
q
1 0 0 1 0 93 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (The ) Tj /F3 10 Tf 0 0 0 rg (FunctionMaker ) Tj /F2 10 Tf 0 0 .501961 rg (class) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Getting the source code) Tj T* ET
Q
Q
q
@@ -650,13 +677,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 66.44 0 Td (9) Tj T* -66.44 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (11) Tj T* -60.88 0 Td ET
Q
Q
q
1 0 0 1 0 75 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Getting the source code) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Dealing with third party decorators) Tj T* ET
Q
Q
q
@@ -664,13 +691,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (10) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (11) Tj T* -60.88 0 Td ET
Q
Q
q
1 0 0 1 0 57 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Dealing with third party decorators) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Multiple dispatch) Tj T* ET
Q
Q
q
@@ -678,13 +705,13 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (11) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (13) Tj T* -60.88 0 Td ET
Q
Q
q
1 0 0 1 0 39 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Multiple dispatch) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 .501961 rg (Generics and Abstract Base Classes) Tj T* ET
Q
Q
q
@@ -692,7 +719,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (13) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (15) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -706,7 +733,7 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (15) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (16) Tj T* -60.88 0 Td ET
Q
Q
q
@@ -720,77 +747,70 @@ q
q
0 0 .501961 rg
0 0 .501961 RG
-BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (17) Tj T* -60.88 0 Td ET
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 60.88 0 Td (18) Tj T* -60.88 0 Td ET
Q
Q
q
Q
Q
+
+endstream
+endobj
+100 0 obj
+<< /Length 7414 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 218.0236 cm
-q
-BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Compatibility notes) Tj T* ET
-Q
-Q
-q
-1 0 0 1 62.69291 128.0236 cm
+1 0 0 1 62.69291 744.0236 cm
q
-BT 1 0 0 1 0 74 Tm 1.033876 Tw 12 TL /F1 10 Tf 0 0 0 rg (The decorator module is over ten years old, but still alive and kicking. It is used by several frameworks) Tj T* 0 Tw .917356 Tw (and has been stable for a ) Tj /F4 10 Tf (long ) Tj /F1 10 Tf (time. Even version 4.0 is compatible with the past, except for one thing:) Tj T* 0 Tw 1.121654 Tw (support for Python 2.4 and 2.5 has been dropped. That decision made it possible to use a single code) Tj T* 0 Tw .453988 Tw (base both for Python 2.X and Python 3.X. This is a ) Tj /F4 10 Tf (huge ) Tj /F1 10 Tf (bonus, since I could remove over 2,000 lines of) Tj T* 0 Tw 2.794597 Tw (duplicated documentation. Having to maintain separate docs for Python 2 and Python 3 effectively) Tj T* 0 Tw 1.61311 Tw (stopped any development on the module for several years. Moreover, it is now trivial to distribute the) Tj T* 0 Tw (module as a wheel since 2to3 is no more required.) Tj T* ET
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Introduction) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 98.02362 cm
+1 0 0 1 62.69291 606.0236 cm
q
-0 0 0 rg
-BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .999987 Tw (This version supports all Python releases from 2.6 up to 3.5. If you need to support ancient versions of) Tj T* 0 Tw (Python, stick with the decorator module version 3.4.2.) Tj T* ET
+BT 1 0 0 1 0 122 Tm 1.033876 Tw 12 TL /F1 10 Tf 0 0 0 rg (The decorator module is over ten years old, but still alive and kicking. It is used by several frameworks) Tj T* 0 Tw 1.737356 Tw (\(IPython, scipy, pyramid,...\) and has been stable for a ) Tj /F4 10 Tf (long ) Tj /F1 10 Tf (time. It is your best option if you want to) Tj T* 0 Tw .607984 Tw (preserve the signature of decorated functions in a consistent way across Python releases. Version 4.0 is) Tj T* 0 Tw 1.318221 Tw (fully compatible with the past, except for one thing: support for Python 2.4 and 2.5 has been dropped.) Tj T* 0 Tw .843488 Tw (That decision made it possible to use a single code base both for Python 2.X and Python 3.X. This is a) Tj T* 0 Tw 2.409982 Tw /F4 10 Tf (huge ) Tj /F1 10 Tf (bonus, since I could remove over 2,000 lines of duplicated documentation/doctests. Having to) Tj T* 0 Tw .18561 Tw (maintain separate docs for Python 2 and Python 3 effectively stopped any development on the module for) Tj T* 0 Tw 2.207209 Tw (several years. Moreover, it is now trivial to distribute the module as a wheel since 2to3 is no more) Tj T* 0 Tw .038935 Tw (required. Since Python 2.5 has been released 9 years ago, I felt that it was reasonable to drop the support) Tj T* 0 Tw .012209 Tw (for it. If you need to support ancient versions of Python, stick with the decorator module version 3.4.2. This) Tj T* 0 Tw (version supports all Python releases from 2.6 up to 3.5, which currently is still in beta status.) Tj T* ET
Q
Q
-
-endstream
-endobj
-96 0 obj
-<< /Length 7609 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 744.0236 cm
+1 0 0 1 62.69291 573.0236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (What's new) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 666.0236 cm
+1 0 0 1 62.69291 483.0236 cm
q
-BT 1 0 0 1 0 62 Tm 2.334692 Tw 12 TL /F1 10 Tf 0 0 0 rg (Since now there is a single manual for all Python versions, I took the occasion for overhauling the) Tj T* 0 Tw .042765 Tw (documentation. Therefore, even if you are an old time user, you may want to read the manual again, since) Tj T* 0 Tw 12.44442 Tw (several examples have been improved. A new utility function ) Tj /F3 10 Tf 0 0 0 rg (decorate\(func,) Tj T* 0 Tw 4.299213 Tw (caller\)`) Tj ( ) Tj (has) Tj ( ) Tj (been) Tj ( ) Tj (added,) Tj ( ) Tj (doing) Tj ( ) Tj (the) Tj ( ) Tj (same) Tj ( ) Tj (job) Tj ( ) Tj (that) Tj ( ) Tj (in) Tj ( ) Tj (the) Tj ( ) Tj (past) Tj ( ) Tj (was) Tj ( ) Tj (done) Tj T* 0 Tw 1.516412 Tw (by) Tj ( ) Tj (``decorator\(caller,) Tj ( ) Tj (func\)) Tj /F1 10 Tf 0 0 0 rg (. The old functionality is still there for compatibility sake, but it is) Tj T* 0 Tw (deprecated and not documented anymore.) Tj T* ET
+BT 1 0 0 1 0 74 Tm 2.334692 Tw 12 TL /F1 10 Tf 0 0 0 rg (Since now there is a single manual for all Python versions, I took the occasion for overhauling the) Tj T* 0 Tw .691098 Tw (documentation. Therefore, even if you are an old time user, you may want to read the docs again, since) Tj T* 0 Tw .311984 Tw (several examples have been improved. The packaging has been improved and now I am also distributing) Tj T* 0 Tw 2.16686 Tw (the code in wheel format. The integration with setuptools has been improved and now you can use) Tj T* 0 Tw .166412 Tw /F3 10 Tf 0 0 0 rg (python) Tj ( ) Tj (setup.py) Tj ( ) Tj (test ) Tj /F1 10 Tf 0 0 0 rg (to run the tests. A new utility function ) Tj /F3 10 Tf 0 0 0 rg (decorate\(func, caller\) ) Tj /F1 10 Tf 0 0 0 rg (has been) Tj T* 0 Tw 3.003318 Tw (added, doing the same job that in the past was done by ) Tj /F3 10 Tf 0 0 0 rg (decorator\(caller,) Tj ( ) Tj (func\)) Tj /F1 10 Tf 0 0 0 rg (. The old) Tj T* 0 Tw (functionality is still there for compatibility sake, but it is deprecated and not documented anymore.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 576.0236 cm
+1 0 0 1 62.69291 393.0236 cm
q
-BT 1 0 0 1 0 74 Tm 2.311318 Tw 12 TL /F1 10 Tf 0 0 0 rg (Apart from that, there are no changes. There is a new experimental feature, though. The decorator) Tj T* 0 Tw 1.24784 Tw (module now include an implementation of generic \(multiple dispatch\) functions. The API is designed to) Tj T* 0 Tw 2.114597 Tw (mimic the one of ) Tj /F4 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (but the implementation is much simpler and more general;) Tj T* 0 Tw .144692 Tw (moreover it preserves the signature of the decorated functions. For the moment it is there to exemplify the) Tj T* 0 Tw 1.08881 Tw (power of the module. In the future it could change and/or be enhanced/optimized; on the other hand, it) Tj T* 0 Tw .098409 Tw (could even become deprecated. Such is the fate of experimental features. In any case it is only 40 lines of) Tj T* 0 Tw (code. Take it as food for thought.) Tj T* ET
+BT 1 0 0 1 0 74 Tm 4.582126 Tw 12 TL /F1 10 Tf 0 0 0 rg (Apart from that, there is a new experimental feature. The decorator module now includes an) Tj T* 0 Tw 3.31284 Tw (implementation of generic \(multiple dispatch\) functions. The API is designed to mimic the one of) Tj T* 0 Tw 2.42998 Tw /F4 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (but the implementation is much simpler and more general; moreover all the) Tj T* 0 Tw .274651 Tw (decorators involved preserve the signature of the decorated functions. For the moment the facility is there) Tj T* 0 Tw .359985 Tw (mostly to exemplify the power of the module. In the future it could change and/or be enhanced/optimized;) Tj T* 0 Tw 1.252927 Tw (on the other hand, it could even become deprecated. Such is the fate of experimental features. In any) Tj T* 0 Tw (case it is very short and compact, so you can extract it for your own use. Take it as food for thought.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 543.0236 cm
+1 0 0 1 62.69291 360.0236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Usefulness of decorators) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 477.0236 cm
+1 0 0 1 62.69291 294.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 50 Tm /F1 10 Tf 12 TL 3.995366 Tw (Python decorators are an interesting example of why syntactic sugar matters. In principle, their) Tj T* 0 Tw .151235 Tw (introduction in Python 2.4 changed nothing, since they do not provide any new functionality which was not) Tj T* 0 Tw 2.238555 Tw (already present in the language. In practice, their introduction has significantly changed the way we) Tj T* 0 Tw .098409 Tw (structure our programs in Python. I believe the change is for the best, and that decorators are a great idea) Tj T* 0 Tw (since:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 471.0236 cm
+1 0 0 1 62.69291 288.0236 cm
Q
q
-1 0 0 1 62.69291 471.0236 cm
+1 0 0 1 62.69291 288.0236 cm
Q
q
-1 0 0 1 62.69291 459.0236 cm
+1 0 0 1 62.69291 276.0236 cm
0 0 0 rg
BT /F1 10 Tf 12 TL ET
q
@@ -811,10 +831,10 @@ q
Q
Q
q
-1 0 0 1 62.69291 453.0236 cm
+1 0 0 1 62.69291 270.0236 cm
Q
q
-1 0 0 1 62.69291 441.0236 cm
+1 0 0 1 62.69291 258.0236 cm
0 0 0 rg
BT /F1 10 Tf 12 TL ET
q
@@ -835,10 +855,10 @@ q
Q
Q
q
-1 0 0 1 62.69291 435.0236 cm
+1 0 0 1 62.69291 252.0236 cm
Q
q
-1 0 0 1 62.69291 423.0236 cm
+1 0 0 1 62.69291 240.0236 cm
0 0 0 rg
BT /F1 10 Tf 12 TL ET
q
@@ -859,10 +879,10 @@ q
Q
Q
q
-1 0 0 1 62.69291 417.0236 cm
+1 0 0 1 62.69291 234.0236 cm
Q
q
-1 0 0 1 62.69291 405.0236 cm
+1 0 0 1 62.69291 222.0236 cm
0 0 0 rg
BT /F1 10 Tf 12 TL ET
q
@@ -883,48 +903,55 @@ q
Q
Q
q
-1 0 0 1 62.69291 405.0236 cm
+1 0 0 1 62.69291 222.0236 cm
Q
q
-1 0 0 1 62.69291 363.0236 cm
+1 0 0 1 62.69291 180.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .848876 Tw (Still, as of now, writing custom decorators correctly requires some experience and it is not as easy as it) Tj T* 0 Tw 1.049269 Tw (could be. For instance, typical implementations of decorators involve nested functions, and we all know) Tj T* 0 Tw (that flat is better than nested.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 309.0236 cm
+1 0 0 1 62.69291 126.0236 cm
q
BT 1 0 0 1 0 38 Tm 1.093735 Tw 12 TL /F1 10 Tf 0 0 0 rg (The aim of the ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (module it to simplify the usage of decorators for the average programmer,) Tj T* 0 Tw 2.456136 Tw (and to popularize decorators by showing various non-trivial examples. Of course, as all techniques,) Tj T* 0 Tw 2.234987 Tw (decorators can be abused \(I have seen that\) and you should not try to solve every problem with a) Tj T* 0 Tw (decorator, just because you can.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 279.0236 cm
+1 0 0 1 62.69291 96.02362 cm
q
BT 1 0 0 1 0 14 Tm .13561 Tw 12 TL /F1 10 Tf 0 0 0 rg (You may find the source code for all the examples discussed here in the ) Tj /F3 10 Tf 0 0 0 rg (documentation.py ) Tj /F1 10 Tf 0 0 0 rg (file, which) Tj T* 0 Tw (contains the documentation you are reading in the form of doctests.) Tj T* ET
Q
Q
+
+endstream
+endobj
+101 0 obj
+<< /Length 12505 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 246.0236 cm
+1 0 0 1 62.69291 744.0236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Definitions) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 204.0236 cm
+1 0 0 1 62.69291 702.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 2.37561 Tw (Technically speaking, any Python object which can be called with one argument can be used as a) Tj T* 0 Tw .472339 Tw (decorator. However, this definition is somewhat too large to be really useful. It is more convenient to split) Tj T* 0 Tw (the generic class of decorators in two subclasses:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 198.0236 cm
+1 0 0 1 62.69291 696.0236 cm
Q
q
-1 0 0 1 62.69291 198.0236 cm
+1 0 0 1 62.69291 696.0236 cm
Q
q
-1 0 0 1 62.69291 174.0236 cm
+1 0 0 1 62.69291 672.0236 cm
0 0 0 rg
BT /F1 10 Tf 12 TL ET
q
@@ -944,10 +971,10 @@ q
Q
Q
q
-1 0 0 1 62.69291 168.0236 cm
+1 0 0 1 62.69291 666.0236 cm
Q
q
-1 0 0 1 62.69291 144.0236 cm
+1 0 0 1 62.69291 642.0236 cm
0 0 0 rg
BT /F1 10 Tf 12 TL ET
q
@@ -967,49 +994,42 @@ q
Q
Q
q
-1 0 0 1 62.69291 144.0236 cm
+1 0 0 1 62.69291 642.0236 cm
Q
q
-1 0 0 1 62.69291 102.0236 cm
+1 0 0 1 62.69291 600.0236 cm
q
BT 1 0 0 1 0 26 Tm 2.832706 Tw 12 TL /F1 10 Tf 0 0 0 rg (Signature-changing decorators have their use: for instance the builtin classes ) Tj /F3 10 Tf 0 0 0 rg (staticmethod ) Tj /F1 10 Tf 0 0 0 rg (and) Tj T* 0 Tw 1.506651 Tw /F3 10 Tf 0 0 0 rg (classmethod ) Tj /F1 10 Tf 0 0 0 rg (are in this group, since they take functions and return descriptor objects which are not) Tj T* 0 Tw (functions, nor callables.) Tj T* ET
Q
Q
-
-endstream
-endobj
-97 0 obj
-<< /Length 14805 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 741.0236 cm
+1 0 0 1 62.69291 570.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.735814 Tw (However, signature-preserving decorators are more common and easier to reason about; in particular) Tj T* 0 Tw (signature-preserving decorators can be composed together whereas other decorators in general cannot.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 711.0236 cm
+1 0 0 1 62.69291 540.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .494983 Tw (Writing signature-preserving decorators from scratch is not that obvious, especially if one wants to define) Tj T* 0 Tw (proper decorators that can accept functions with any signature. A simple example will clarify the issue.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 678.0236 cm
+1 0 0 1 62.69291 507.0236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Statement of the problem) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 600.0236 cm
+1 0 0 1 62.69291 429.0236 cm
q
BT 1 0 0 1 0 62 Tm .351235 Tw 12 TL /F1 10 Tf 0 0 0 rg (A very common use case for decorators is the memoization of functions. A ) Tj /F3 10 Tf 0 0 0 rg (memoize ) Tj /F1 10 Tf 0 0 0 rg (decorator works by) Tj T* 0 Tw .871988 Tw (caching the result of the function call in a dictionary, so that the next time the function is called with the) Tj T* 0 Tw 2.350651 Tw (same input parameters the result is retrieved from the cache and not recomputed. There are many) Tj T* 0 Tw 2.92247 Tw (implementations of ) Tj /F3 10 Tf 0 0 0 rg (memoize ) Tj /F1 10 Tf 0 0 0 rg (in ) Tj 0 0 .501961 rg (http://www.python.org/moin/PythonDecoratorLibrary) Tj 0 0 0 rg (, but they do not) Tj T* 0 Tw 2.683984 Tw (preserve the signature. A simple implementation could be the following \(notice that in general it is) Tj T* 0 Tw (impossible to memoize correctly something that depends on non-hashable arguments\):) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 434.8236 cm
+1 0 0 1 62.69291 263.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -1183,26 +1203,26 @@ Q
Q
Q
q
-1 0 0 1 62.69291 378.8236 cm
+1 0 0 1 62.69291 207.8236 cm
q
BT 1 0 0 1 0 38 Tm 1.801412 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here we used the ) Tj 0 0 .501961 rg (functools.update_wrapper ) Tj 0 0 0 rg (utility, which has been added in Python 2.5 expressly to) Tj T* 0 Tw .91686 Tw (simplify the definition of decorators \(in older versions of Python you need to copy the function attributes) Tj T* 0 Tw .580814 Tw /F3 10 Tf 0 0 0 rg (__name__) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F3 10 Tf 0 0 0 rg (__doc__) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F3 10 Tf 0 0 0 rg (__module__ ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (__dict__ ) Tj /F1 10 Tf 0 0 0 rg (from the original function to the decorated function) Tj T* 0 Tw (by hand\).) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 336.8236 cm
+1 0 0 1 62.69291 165.8236 cm
q
BT 1 0 0 1 0 26 Tm 2.517126 Tw 12 TL /F1 10 Tf 0 0 0 rg (The implementation above works in the sense that the decorator can accept functions with generic) Tj T* 0 Tw 1.233615 Tw (signatures; unfortunately this implementation does ) Tj /F4 10 Tf (not ) Tj /F1 10 Tf (define a signature-preserving decorator, since in) Tj T* 0 Tw (general ) Tj /F3 10 Tf 0 0 0 rg (memoize_uw ) Tj /F1 10 Tf 0 0 0 rg (returns a function with a ) Tj /F4 10 Tf (different signature ) Tj /F1 10 Tf (from the original function.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 318.8236 cm
+1 0 0 1 62.69291 147.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Consider for instance the following case:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 237.6236 cm
+1 0 0 1 62.69291 90.62362 cm
q
q
1 0 0 1 0 0 cm
@@ -1212,23 +1232,50 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 72 re B*
+n -6 -6 468.6898 48 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 48 66 12 re f*
+n 0 24 66 12 re f*
.960784 .960784 .862745 rg
-n 0 36 18 12 re f*
+n 0 12 18 12 re f*
.960784 .960784 .862745 rg
-n 24 36 12 12 re f*
+n 24 12 12 12 re f*
.960784 .960784 .862745 rg
-n 36 36 6 12 re f*
+n 36 12 6 12 re f*
.960784 .960784 .862745 rg
-n 42 36 6 12 re f*
+n 42 12 6 12 re f*
.960784 .960784 .862745 rg
-n 48 36 12 12 re f*
+n 48 12 12 12 re f*
.960784 .960784 .862745 rg
-n 24 24 192 12 re f*
+n 24 0 192 12 re f*
+BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .666667 .133333 1 rg (@memoize_uw) Tj 0 0 0 rg T* /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (f1) Tj 0 0 0 rg (\() Tj 0 0 0 rg (x) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj .729412 .129412 .129412 rg ("Simulate some long computation") Tj 0 0 0 rg T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+102 0 obj
+<< /Length 16560 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 727.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
.960784 .960784 .862745 rg
n 24 12 24 12 re f*
.960784 .960784 .862745 rg
@@ -1245,20 +1292,20 @@ n 96 12 6 12 re f*
n 24 0 36 12 re f*
.960784 .960784 .862745 rg
n 66 0 6 12 re f*
-BT 1 0 0 1 0 50 Tm 12 TL /F3 10 Tf .666667 .133333 1 rg (@memoize_uw) Tj 0 0 0 rg T* /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (f1) Tj 0 0 0 rg (\() Tj 0 0 0 rg (x) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj .729412 .129412 .129412 rg ("Simulate some long computation") Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (time) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (sleep) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (x) Tj T* ET
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (time) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (sleep) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (x) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 205.6236 cm
+1 0 0 1 62.69291 695.8236 cm
q
BT 1 0 0 1 0 14 Tm .26311 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here the original function takes a single argument named ) Tj /F3 10 Tf 0 0 0 rg (x) Tj /F1 10 Tf 0 0 0 rg (, but the decorated function takes any number) Tj T* 0 Tw (of arguments and keyword arguments:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 148.4236 cm
+1 0 0 1 62.69291 638.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -1344,20 +1391,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 92.42362 cm
+1 0 0 1 62.69291 582.6236 cm
q
BT 1 0 0 1 0 38 Tm .411235 Tw 12 TL /F1 10 Tf 0 0 0 rg (This means that introspection tools such as ) Tj /F4 10 Tf (pydoc ) Tj /F1 10 Tf (will give wrong informations about the signature of ) Tj /F3 10 Tf 0 0 0 rg (f1) Tj /F1 10 Tf 0 0 0 rg (,) Tj T* 0 Tw .010488 Tw (unless you are using a recent of Python 3.X. This is pretty bad: ) Tj /F4 10 Tf (pydoc ) Tj /F1 10 Tf (will tell you that the function accepts) Tj T* 0 Tw .624431 Tw (a generic signature ) Tj /F3 10 Tf 0 0 0 rg (*args) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F3 10 Tf 0 0 0 rg (**kw) Tj /F1 10 Tf 0 0 0 rg (, but when you try to call the function with more than an argument, you) Tj T* 0 Tw (will get an error:) Tj T* ET
Q
Q
-
-endstream
-endobj
-98 0 obj
-<< /Length 16084 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 703.8236 cm
+1 0 0 1 62.69291 513.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -1437,25 +1477,25 @@ Q
Q
Q
q
-1 0 0 1 62.69291 671.8236 cm
+1 0 0 1 62.69291 481.4236 cm
q
-BT 1 0 0 1 0 14 Tm 1.545814 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice even in Python 3.5 ) Tj /F4 10 Tf 0 0 0 rg (inspect.getargspec ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (inspect.getfullargspec ) Tj /F1 10 Tf 0 0 0 rg (\(which are deprecated in that) Tj T* 0 Tw (release\) will give the wrong signature. ) Tj /F4 10 Tf 0 0 0 rg (inspect.signature ) Tj /F1 10 Tf 0 0 0 rg (will return the right signature on the surface.) Tj T* ET
+BT 1 0 0 1 0 14 Tm 1.545814 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice even in Python 3.5 ) Tj /F4 10 Tf 0 0 0 rg (inspect.getargspec ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (inspect.getfullargspec ) Tj /F1 10 Tf 0 0 0 rg (\(which are deprecated in that) Tj T* 0 Tw (release\) will give the wrong signature.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 638.8236 cm
+1 0 0 1 62.69291 448.4236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (The solution) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 596.8236 cm
+1 0 0 1 62.69291 406.4236 cm
q
BT 1 0 0 1 0 26 Tm 3.313984 Tw 12 TL /F1 10 Tf 0 0 0 rg (The solution is to provide a generic factory of generators, which hides the complexity of making) Tj T* 0 Tw 3.962976 Tw (signature-preserving decorators from the application programmer. The ) Tj /F3 10 Tf 0 0 0 rg (decorate ) Tj /F1 10 Tf 0 0 0 rg (function in the) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (module is such a factory:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 563.6236 cm
+1 0 0 1 62.69291 373.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -1489,13 +1529,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 507.6236 cm
+1 0 0 1 62.69291 317.2236 cm
q
BT 1 0 0 1 0 38 Tm 2.144983 Tw 12 TL /F3 10 Tf 0 0 0 rg (decorate ) Tj /F1 10 Tf 0 0 0 rg (takes two arguments, a caller function describing the functionality of the decorator and a) Tj T* 0 Tw 2.594983 Tw (function to be decorated; it returns the decorated function. The caller function must have signature) Tj T* 0 Tw .19311 Tw /F3 10 Tf 0 0 0 rg (\(f,) Tj ( ) Tj (*args,) Tj ( ) Tj (**kw\) ) Tj /F1 10 Tf 0 0 0 rg (and it must call the original function ) Tj /F3 10 Tf 0 0 0 rg (f ) Tj /F1 10 Tf 0 0 0 rg (with arguments ) Tj /F3 10 Tf 0 0 0 rg (args ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (kw) Tj /F1 10 Tf 0 0 0 rg (, implementing) Tj T* 0 Tw (the wanted capability, i.e. memoization in this case:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 378.4236 cm
+1 0 0 1 62.69291 188.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -1635,14 +1675,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 358.4236 cm
+1 0 0 1 62.69291 168.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (At this point you can define your decorator as follows:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 301.2236 cm
+1 0 0 1 62.69291 110.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -1695,21 +1735,28 @@ Q
Q
Q
Q
+
+endstream
+endobj
+103 0 obj
+<< /Length 18522 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 257.2236 cm
+1 0 0 1 62.69291 729.0236 cm
q
BT 1 0 0 1 0 26 Tm .12561 Tw 12 TL /F1 10 Tf 0 0 0 rg (The difference with respect to the ) Tj /F3 10 Tf 0 0 0 rg (memoize_uw ) Tj /F1 10 Tf 0 0 0 rg (approach, which is based on nested functions, is that the) Tj T* 0 Tw .598876 Tw (decorator module forces you to lift the inner function at the outer level. Moreover, you are forced to pass) Tj T* 0 Tw (explicitly the function you want to decorate, there are no closures.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 239.2236 cm
+1 0 0 1 62.69291 711.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Here is a test of usage:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 98.02362 cm
+1 0 0 1 62.69291 569.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -1801,20 +1848,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 78.02362 cm
+1 0 0 1 62.69291 549.8236 cm
q
BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The signature of ) Tj /F3 10 Tf 0 0 0 rg (heavy_computation ) Tj /F1 10 Tf 0 0 0 rg (is the one you would expect:) Tj T* ET
Q
Q
-
-endstream
-endobj
-99 0 obj
-<< /Length 21513 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 727.8236 cm
+1 0 0 1 62.69291 504.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -1886,19 +1926,19 @@ Q
Q
Q
q
-1 0 0 1 62.69291 694.8236 cm
+1 0 0 1 62.69291 471.6236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (A ) Tj /F3 17.5 Tf 0 0 0 rg (trace ) Tj /F2 17.5 Tf 0 0 0 rg (decorator) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 664.8236 cm
+1 0 0 1 62.69291 441.6236 cm
q
BT 1 0 0 1 0 14 Tm .479398 Tw 12 TL /F1 10 Tf 0 0 0 rg (As an additional example, here is how you can define a trivial ) Tj /F3 10 Tf 0 0 0 rg (trace ) Tj /F1 10 Tf 0 0 0 rg (decorator, which prints a message) Tj T* 0 Tw (everytime the traced function is called:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 595.6236 cm
+1 0 0 1 62.69291 372.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -2048,7 +2088,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 550.4236 cm
+1 0 0 1 62.69291 327.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -2092,14 +2132,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 530.4236 cm
+1 0 0 1 62.69291 307.2236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Here is an example of usage:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 473.2236 cm
+1 0 0 1 62.69291 250.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -2143,13 +2183,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 453.2236 cm
+1 0 0 1 62.69291 230.0236 cm
q
BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (It is immediate to verify that ) Tj /F3 10 Tf 0 0 0 rg (f1 ) Tj /F1 10 Tf 0 0 0 rg (works) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 408.0236 cm
+1 0 0 1 62.69291 184.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -2199,14 +2239,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 388.0236 cm
+1 0 0 1 62.69291 164.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (and it that it has the correct signature:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 342.8236 cm
+1 0 0 1 62.69291 119.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -2282,14 +2322,21 @@ Q
Q
Q
q
-1 0 0 1 62.69291 322.8236 cm
+1 0 0 1 62.69291 99.62362 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The same decorator works with functions of any signature:) Tj T* ET
Q
Q
+
+endstream
+endobj
+104 0 obj
+<< /Length 17627 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 193.6236 cm
+1 0 0 1 62.69291 643.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -2473,26 +2520,19 @@ Q
Q
Q
q
-1 0 0 1 62.69291 160.6236 cm
+1 0 0 1 62.69291 610.8236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Function annotations) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 106.6236 cm
+1 0 0 1 62.69291 556.8236 cm
q
BT 1 0 0 1 0 38 Tm 1.937318 Tw 12 TL /F1 10 Tf 0 0 0 rg (Python 3 introduced the concept of ) Tj 0 0 .501961 rg (function annotations) Tj 0 0 0 rg (,i.e. the ability to annotate the signature of a) Tj T* 0 Tw 2.24816 Tw (function with additional information, stored in a dictionary named ) Tj /F3 10 Tf 0 0 0 rg (__annotations__) Tj /F1 10 Tf 0 0 0 rg (. The decorator) Tj T* 0 Tw 1.923735 Tw (module, starting from release 3.3, is able to understand and to preserve the annotations. Here is an) Tj T* 0 Tw (example:) Tj T* ET
Q
Q
-
-endstream
-endobj
-100 0 obj
-<< /Length 20638 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 703.8236 cm
+1 0 0 1 62.69291 487.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -2582,13 +2622,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 671.8236 cm
+1 0 0 1 62.69291 455.6236 cm
q
BT 1 0 0 1 0 14 Tm .596647 Tw 12 TL /F1 10 Tf 0 0 0 rg (In order to introspect functions with annotations, one needs the utility ) Tj /F3 10 Tf 0 0 0 rg (inspect.getfullargspec) Tj /F1 10 Tf 0 0 0 rg (, new) Tj T* 0 Tw (in Python 3:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 494.6236 cm
+1 0 0 1 62.69291 278.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -2742,13 +2782,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 474.6236 cm
+1 0 0 1 62.69291 258.4236 cm
q
BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (You can check that the ) Tj /F3 10 Tf 0 0 0 rg (__annotations__ ) Tj /F1 10 Tf 0 0 0 rg (dictionary is preserved:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 429.4236 cm
+1 0 0 1 62.69291 213.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -2794,25 +2834,32 @@ Q
Q
Q
q
-1 0 0 1 62.69291 373.4236 cm
+1 0 0 1 62.69291 157.2236 cm
q
BT 1 0 0 1 0 38 Tm .84284 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here ) Tj /F3 10 Tf 0 0 0 rg (f.__wrapped__ ) Tj /F1 10 Tf 0 0 0 rg (is the original undecorated function. Such an attribute is added to be consistent) Tj T* 0 Tw .057126 Tw (with the way ) Tj /F4 10 Tf 0 0 0 rg (functools.update_wrapper ) Tj /F1 10 Tf 0 0 0 rg (work. Another attribute which is copied from the original function is) Tj T* 0 Tw 1.67936 Tw /F4 10 Tf 0 0 0 rg (__qualname) Tj /F1 10 Tf 0 0 0 rg (, the qualified name. This is a concept introduced in Python 3. In Python 2 the decorator) Tj T* 0 Tw (module will still add a qualified name, but its value will always be ) Tj /F4 10 Tf 0 0 0 rg (None) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
Q
Q
+
+endstream
+endobj
+105 0 obj
+<< /Length 20355 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 340.4236 cm
+1 0 0 1 62.69291 744.0236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (decorator.decorator) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 286.4236 cm
+1 0 0 1 62.69291 690.0236 cm
q
BT 1 0 0 1 0 38 Tm .643876 Tw 12 TL /F1 10 Tf 0 0 0 rg (It may be annoying to write a caller function \(like the ) Tj /F3 10 Tf 0 0 0 rg (_trace ) Tj /F1 10 Tf 0 0 0 rg (function above\) and then a trivial wrapper) Tj T* 0 Tw 2.056342 Tw (\() Tj /F3 10 Tf 0 0 0 rg (def) Tj ( ) Tj (trace\(f\):) Tj ( ) Tj (return) Tj ( ) Tj (decorate\(f,) Tj ( ) Tj (_trace\)) Tj /F1 10 Tf 0 0 0 rg (\) every time. For this reason, the ) Tj /F3 10 Tf 0 0 0 rg (decorator) Tj T* 0 Tw .49284 Tw /F1 10 Tf 0 0 0 rg (module provides an easy shortcut to convert the caller function into a signature-preserving decorator: the) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (function:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 229.2236 cm
+1 0 0 1 62.69291 632.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -2886,13 +2933,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 173.2236 cm
+1 0 0 1 62.69291 576.8236 cm
q
BT 1 0 0 1 0 38 Tm 1.319982 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (function can be used as a signature-changing decorator, just as ) Tj /F3 10 Tf 0 0 0 rg (classmethod ) Tj /F1 10 Tf 0 0 0 rg (and) Tj T* 0 Tw 1.945976 Tw /F3 10 Tf 0 0 0 rg (staticmethod) Tj /F1 10 Tf 0 0 0 rg (. However, ) Tj /F3 10 Tf 0 0 0 rg (classmethod ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (staticmethod ) Tj /F1 10 Tf 0 0 0 rg (return generic objects which are not) Tj T* 0 Tw 1.086342 Tw (callable, while ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (returns signature-preserving decorators, i.e. functions of a single argument.) Tj T* 0 Tw (For instance, you can write directly) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 92.02362 cm
+1 0 0 1 62.69291 495.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3057,21 +3104,14 @@ Q
Q
Q
Q
-
-endstream
-endobj
-101 0 obj
-<< /Length 18242 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 753.0236 cm
+1 0 0 1 62.69291 475.6236 cm
q
BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (and now ) Tj /F3 10 Tf 0 0 0 rg (trace ) Tj /F1 10 Tf 0 0 0 rg (will be a decorator.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 707.8236 cm
+1 0 0 1 62.69291 430.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -3115,14 +3155,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 687.8236 cm
+1 0 0 1 62.69291 410.4236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Here is an example of usage:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 606.6236 cm
+1 0 0 1 62.69291 329.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -3182,19 +3222,19 @@ Q
Q
Q
q
-1 0 0 1 62.69291 573.6236 cm
+1 0 0 1 62.69291 296.2236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (blocking) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 531.6236 cm
+1 0 0 1 62.69291 254.2236 cm
q
BT 1 0 0 1 0 26 Tm 1.224692 Tw 12 TL /F1 10 Tf 0 0 0 rg (Sometimes one has to deal with blocking resources, such as ) Tj /F3 10 Tf 0 0 0 rg (stdin) Tj /F1 10 Tf 0 0 0 rg (, and sometimes it is best to have) Tj T* 0 Tw .266235 Tw (back a "busy" message than to block everything. This behavior can be implemented with a suitable family) Tj T* 0 Tw (of decorators, where the parameter is the busy message:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 342.4236 cm
+1 0 0 1 62.69291 89.02362 cm
q
q
1 0 0 1 0 0 cm
@@ -3204,161 +3244,188 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 180 re B*
+n -6 -6 468.6898 156 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 156 18 12 re f*
+n 0 132 18 12 re f*
.960784 .960784 .862745 rg
-n 24 156 48 12 re f*
+n 24 132 48 12 re f*
.960784 .960784 .862745 rg
-n 72 156 6 12 re f*
+n 72 132 6 12 re f*
.960784 .960784 .862745 rg
-n 78 156 54 12 re f*
+n 78 132 54 12 re f*
.960784 .960784 .862745 rg
-n 132 156 12 12 re f*
+n 132 132 12 12 re f*
.960784 .960784 .862745 rg
-n 24 144 18 12 re f*
+n 24 120 18 12 re f*
.960784 .960784 .862745 rg
-n 48 144 54 12 re f*
+n 48 120 54 12 re f*
.960784 .960784 .862745 rg
-n 102 144 6 12 re f*
+n 102 120 6 12 re f*
.960784 .960784 .862745 rg
-n 108 144 6 12 re f*
+n 108 120 6 12 re f*
.960784 .960784 .862745 rg
-n 114 144 6 12 re f*
+n 114 120 6 12 re f*
.960784 .960784 .862745 rg
-n 126 144 6 12 re f*
+n 126 120 6 12 re f*
.960784 .960784 .862745 rg
-n 132 144 24 12 re f*
+n 132 120 24 12 re f*
.960784 .960784 .862745 rg
-n 156 144 6 12 re f*
+n 156 120 6 12 re f*
.960784 .960784 .862745 rg
-n 168 144 12 12 re f*
+n 168 120 12 12 re f*
.960784 .960784 .862745 rg
-n 180 144 12 12 re f*
+n 180 120 12 12 re f*
.960784 .960784 .862745 rg
-n 192 144 12 12 re f*
+n 192 120 12 12 re f*
.960784 .960784 .862745 rg
-n 48 132 12 12 re f*
+n 48 108 12 12 re f*
.960784 .960784 .862745 rg
-n 66 132 18 12 re f*
+n 66 108 18 12 re f*
.960784 .960784 .862745 rg
-n 90 132 42 12 re f*
+n 90 108 42 12 re f*
.960784 .960784 .862745 rg
-n 132 132 6 12 re f*
+n 132 108 6 12 re f*
.960784 .960784 .862745 rg
-n 138 132 6 12 re f*
+n 138 108 6 12 re f*
.960784 .960784 .862745 rg
-n 144 132 6 12 re f*
+n 144 108 6 12 re f*
.960784 .960784 .862745 rg
-n 156 132 48 12 re f*
+n 156 108 48 12 re f*
.960784 .960784 .862745 rg
-n 204 132 12 12 re f*
+n 204 108 12 12 re f*
.960784 .960784 .862745 rg
-n 228 132 114 12 re f*
+n 228 108 114 12 re f*
.960784 .960784 .862745 rg
-n 72 120 18 12 re f*
+n 72 96 18 12 re f*
.960784 .960784 .862745 rg
-n 96 120 60 12 re f*
+n 96 96 60 12 re f*
.960784 .960784 .862745 rg
-n 156 120 18 12 re f*
+n 156 96 18 12 re f*
.960784 .960784 .862745 rg
-n 96 108 6 12 re f*
+n 96 84 6 12 re f*
.960784 .960784 .862745 rg
-n 102 108 6 12 re f*
+n 102 84 6 12 re f*
.960784 .960784 .862745 rg
-n 108 108 36 12 re f*
+n 108 84 36 12 re f*
.960784 .960784 .862745 rg
-n 150 108 6 12 re f*
+n 150 84 6 12 re f*
.960784 .960784 .862745 rg
-n 162 108 6 12 re f*
+n 162 84 6 12 re f*
.960784 .960784 .862745 rg
-n 168 108 6 12 re f*
+n 168 84 6 12 re f*
.960784 .960784 .862745 rg
-n 174 108 6 12 re f*
+n 174 84 6 12 re f*
.960784 .960784 .862745 rg
-n 180 108 24 12 re f*
+n 180 84 24 12 re f*
.960784 .960784 .862745 rg
-n 204 108 6 12 re f*
+n 204 84 6 12 re f*
.960784 .960784 .862745 rg
-n 216 108 12 12 re f*
+n 216 84 12 12 re f*
.960784 .960784 .862745 rg
-n 228 108 12 12 re f*
+n 228 84 12 12 re f*
.960784 .960784 .862745 rg
-n 240 108 6 12 re f*
+n 240 84 6 12 re f*
.960784 .960784 .862745 rg
-n 72 96 6 12 re f*
+n 72 72 6 12 re f*
.960784 .960784 .862745 rg
-n 78 96 6 12 re f*
+n 78 72 6 12 re f*
.960784 .960784 .862745 rg
-n 84 96 36 12 re f*
+n 84 72 36 12 re f*
.960784 .960784 .862745 rg
-n 126 96 6 12 re f*
+n 126 72 6 12 re f*
.960784 .960784 .862745 rg
-n 138 96 54 12 re f*
+n 138 72 54 12 re f*
.960784 .960784 .862745 rg
-n 192 96 6 12 re f*
+n 192 72 6 12 re f*
.960784 .960784 .862745 rg
-n 198 96 36 12 re f*
+n 198 72 36 12 re f*
.960784 .960784 .862745 rg
-n 234 96 6 12 re f*
+n 234 72 6 12 re f*
.960784 .960784 .862745 rg
-n 240 96 24 12 re f*
+n 240 72 24 12 re f*
.960784 .960784 .862745 rg
-n 264 96 6 12 re f*
+n 264 72 6 12 re f*
.960784 .960784 .862745 rg
-n 276 96 60 12 re f*
+n 276 72 60 12 re f*
.960784 .960784 .862745 rg
-n 336 96 6 12 re f*
+n 336 72 6 12 re f*
.960784 .960784 .862745 rg
-n 72 84 6 12 re f*
+n 72 60 6 12 re f*
.960784 .960784 .862745 rg
-n 78 84 6 12 re f*
+n 78 60 6 12 re f*
.960784 .960784 .862745 rg
-n 84 84 36 12 re f*
+n 84 60 36 12 re f*
.960784 .960784 .862745 rg
-n 120 84 6 12 re f*
+n 120 60 6 12 re f*
.960784 .960784 .862745 rg
-n 126 84 30 12 re f*
+n 126 60 30 12 re f*
.960784 .960784 .862745 rg
-n 156 84 12 12 re f*
+n 156 60 12 12 re f*
.960784 .960784 .862745 rg
-n 72 72 36 12 re f*
+n 72 48 36 12 re f*
.960784 .960784 .862745 rg
-n 114 72 54 12 re f*
+n 114 48 54 12 re f*
.960784 .960784 .862745 rg
-n 48 60 24 12 re f*
+n 48 36 24 12 re f*
.960784 .960784 .862745 rg
-n 78 60 6 12 re f*
+n 78 36 6 12 re f*
.960784 .960784 .862745 rg
-n 84 60 6 12 re f*
+n 84 36 6 12 re f*
.960784 .960784 .862745 rg
-n 90 60 36 12 re f*
+n 90 36 36 12 re f*
.960784 .960784 .862745 rg
-n 126 60 6 12 re f*
+n 126 36 6 12 re f*
.960784 .960784 .862745 rg
-n 132 60 42 12 re f*
+n 132 36 42 12 re f*
.960784 .960784 .862745 rg
-n 174 60 18 12 re f*
+n 174 36 18 12 re f*
.960784 .960784 .862745 rg
-n 72 48 36 12 re f*
+n 72 24 36 12 re f*
.960784 .960784 .862745 rg
-n 114 48 54 12 re f*
+n 114 24 54 12 re f*
.960784 .960784 .862745 rg
-n 48 36 24 12 re f*
+n 48 12 24 12 re f*
.960784 .960784 .862745 rg
-n 72 36 6 12 re f*
+n 72 12 6 12 re f*
.960784 .960784 .862745 rg
-n 90 36 282 12 re f*
+n 90 12 282 12 re f*
.960784 .960784 .862745 rg
-n 72 24 18 12 re f*
+n 72 0 18 12 re f*
.960784 .960784 .862745 rg
-n 96 24 6 12 re f*
+n 96 0 6 12 re f*
.960784 .960784 .862745 rg
-n 102 24 6 12 re f*
+n 102 0 6 12 re f*
.960784 .960784 .862745 rg
-n 108 24 36 12 re f*
+n 108 0 36 12 re f*
+BT 1 0 0 1 0 134 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (blocking) Tj 0 0 0 rg (\() Tj 0 0 0 rg (not_avail) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (_blocking) Tj 0 0 0 rg (\() Tj 0 0 0 rg (f) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (if) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf .666667 .133333 1 rg (not) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 .501961 0 rg (hasattr) Tj 0 0 0 rg (\() Tj 0 0 0 rg (f) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("thread") Tj 0 0 0 rg (\):) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# no thread running) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (set_result) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (result) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (thread) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (threading) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Thread) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (None) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (set_result) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (thread) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (start) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (not_avail) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (elif) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (thread) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (isAlive) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (not_avail) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (else) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# the thread is ended, return the stored result) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (del) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (thread) Tj 0 0 0 rg T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+106 0 obj
+<< /Length 18696 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 727.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
.960784 .960784 .862745 rg
n 72 12 36 12 re f*
.960784 .960784 .862745 rg
@@ -3377,20 +3444,20 @@ n 120 0 6 12 re f*
n 126 0 54 12 re f*
.960784 .960784 .862745 rg
n 180 0 6 12 re f*
-BT 1 0 0 1 0 158 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (blocking) Tj 0 0 0 rg (\() Tj 0 0 0 rg (not_avail) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (_blocking) Tj 0 0 0 rg (\() Tj 0 0 0 rg (f) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (if) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf .666667 .133333 1 rg (not) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 .501961 0 rg (hasattr) Tj 0 0 0 rg (\() Tj 0 0 0 rg (f) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("thread") Tj 0 0 0 rg (\):) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# no thread running) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (set_result) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (result) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (thread) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (threading) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Thread) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (None) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (set_result) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (thread) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (start) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (not_avail) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (elif) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (thread) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (isAlive) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (not_avail) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (else) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# the thread is ended, return the stored result) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (del) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (thread) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (result) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (decorator) Tj 0 0 0 rg (\() Tj 0 0 0 rg (_blocking) Tj 0 0 0 rg (\)) Tj T* ET
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (result) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (decorator) Tj 0 0 0 rg (\() Tj 0 0 0 rg (_blocking) Tj 0 0 0 rg (\)) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 310.4236 cm
+1 0 0 1 62.69291 695.8236 cm
q
BT 1 0 0 1 0 14 Tm 1.010651 Tw 12 TL /F1 10 Tf 0 0 0 rg (Functions decorated with ) Tj /F3 10 Tf 0 0 0 rg (blocking ) Tj /F1 10 Tf 0 0 0 rg (will return a busy message if the resource is unavailable, and the) Tj T* 0 Tw (intended result if the resource is available. For instance:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 85.22362 cm
+1 0 0 1 62.69291 446.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -3400,202 +3467,175 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 216 re B*
+n -6 -6 468.6898 240 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 192 6 12 re f*
-.960784 .960784 .862745 rg
-n 6 192 6 12 re f*
+n 0 216 6 12 re f*
.960784 .960784 .862745 rg
-n 12 192 6 12 re f*
+n 6 216 6 12 re f*
.960784 .960784 .862745 rg
-n 24 192 54 12 re f*
+n 12 216 6 12 re f*
.960784 .960784 .862745 rg
-n 78 192 6 12 re f*
+n 24 216 54 12 re f*
.960784 .960784 .862745 rg
-n 84 192 102 12 re f*
+n 78 216 6 12 re f*
.960784 .960784 .862745 rg
-n 186 192 6 12 re f*
+n 84 216 102 12 re f*
.960784 .960784 .862745 rg
-n 0 180 18 12 re f*
+n 186 216 6 12 re f*
.960784 .960784 .862745 rg
-n 24 180 18 12 re f*
+n 0 204 18 12 re f*
.960784 .960784 .862745 rg
-n 48 180 54 12 re f*
+n 24 204 18 12 re f*
.960784 .960784 .862745 rg
-n 102 180 18 12 re f*
+n 48 204 54 12 re f*
.960784 .960784 .862745 rg
-n 0 168 18 12 re f*
+n 102 204 18 12 re f*
.960784 .960784 .862745 rg
-n 48 168 24 12 re f*
+n 0 192 18 12 re f*
.960784 .960784 .862745 rg
-n 72 168 6 12 re f*
+n 48 192 24 12 re f*
.960784 .960784 .862745 rg
-n 78 168 30 12 re f*
+n 72 192 6 12 re f*
.960784 .960784 .862745 rg
-n 108 168 6 12 re f*
+n 78 192 30 12 re f*
.960784 .960784 .862745 rg
-n 114 168 6 12 re f*
+n 108 192 6 12 re f*
.960784 .960784 .862745 rg
-n 120 168 6 12 re f*
+n 114 192 6 12 re f*
.960784 .960784 .862745 rg
-n 132 168 180 12 re f*
+n 120 192 6 12 re f*
.960784 .960784 .862745 rg
-n 0 156 18 12 re f*
+n 132 192 180 12 re f*
.960784 .960784 .862745 rg
-n 48 156 36 12 re f*
+n 0 180 18 12 re f*
.960784 .960784 .862745 rg
-n 90 156 66 12 re f*
+n 48 180 36 12 re f*
.960784 .960784 .862745 rg
-n 0 132 6 12 re f*
+n 90 180 66 12 re f*
.960784 .960784 .862745 rg
-n 6 132 6 12 re f*
+n 0 156 6 12 re f*
.960784 .960784 .862745 rg
-n 12 132 6 12 re f*
+n 6 156 6 12 re f*
.960784 .960784 .862745 rg
-n 24 132 30 12 re f*
+n 12 156 6 12 re f*
.960784 .960784 .862745 rg
-n 54 132 6 12 re f*
+n 24 156 30 12 re f*
.960784 .960784 .862745 rg
-n 60 132 54 12 re f*
+n 54 156 6 12 re f*
.960784 .960784 .862745 rg
-n 114 132 18 12 re f*
+n 60 156 54 12 re f*
.960784 .960784 .862745 rg
-n 144 132 162 12 re f*
+n 114 156 18 12 re f*
.960784 .960784 .862745 rg
-n 0 120 36 12 re f*
+n 144 156 162 12 re f*
.960784 .960784 .862745 rg
-n 42 120 24 12 re f*
+n 0 144 36 12 re f*
.960784 .960784 .862745 rg
-n 72 120 18 12 re f*
+n 42 144 24 12 re f*
.960784 .960784 .862745 rg
-n 0 96 6 12 re f*
+n 72 144 18 12 re f*
.960784 .960784 .862745 rg
-n 6 96 6 12 re f*
+n 0 120 6 12 re f*
.960784 .960784 .862745 rg
-n 12 96 6 12 re f*
+n 6 120 6 12 re f*
.960784 .960784 .862745 rg
-n 24 96 24 12 re f*
+n 12 120 6 12 re f*
.960784 .960784 .862745 rg
-n 48 96 6 12 re f*
+n 24 120 24 12 re f*
.960784 .960784 .862745 rg
-n 54 96 30 12 re f*
+n 48 120 6 12 re f*
.960784 .960784 .862745 rg
-n 84 96 6 12 re f*
+n 54 120 30 12 re f*
.960784 .960784 .862745 rg
-n 90 96 6 12 re f*
+n 84 120 6 12 re f*
.960784 .960784 .862745 rg
-n 96 96 6 12 re f*
+n 90 120 6 12 re f*
.960784 .960784 .862745 rg
-n 0 84 6 12 re f*
+n 96 120 6 12 re f*
.960784 .960784 .862745 rg
-n 6 84 6 12 re f*
+n 0 108 6 12 re f*
.960784 .960784 .862745 rg
-n 12 84 6 12 re f*
+n 6 108 6 12 re f*
.960784 .960784 .862745 rg
-n 24 84 30 12 re f*
+n 12 108 6 12 re f*
.960784 .960784 .862745 rg
-n 54 84 6 12 re f*
+n 24 108 30 12 re f*
.960784 .960784 .862745 rg
-n 60 84 54 12 re f*
+n 54 108 6 12 re f*
.960784 .960784 .862745 rg
-n 114 84 18 12 re f*
+n 60 108 54 12 re f*
.960784 .960784 .862745 rg
-n 144 84 162 12 re f*
+n 114 108 18 12 re f*
.960784 .960784 .862745 rg
-n 0 72 36 12 re f*
+n 144 108 162 12 re f*
.960784 .960784 .862745 rg
-n 42 72 24 12 re f*
+n 0 96 36 12 re f*
.960784 .960784 .862745 rg
-n 72 72 18 12 re f*
+n 42 96 24 12 re f*
.960784 .960784 .862745 rg
-n 0 48 6 12 re f*
+n 72 96 18 12 re f*
.960784 .960784 .862745 rg
-n 6 48 6 12 re f*
+n 0 72 6 12 re f*
.960784 .960784 .862745 rg
-n 12 48 6 12 re f*
+n 6 72 6 12 re f*
.960784 .960784 .862745 rg
-n 24 48 24 12 re f*
+n 12 72 6 12 re f*
.960784 .960784 .862745 rg
-n 48 48 6 12 re f*
+n 24 72 24 12 re f*
.960784 .960784 .862745 rg
-n 54 48 30 12 re f*
+n 48 72 6 12 re f*
.960784 .960784 .862745 rg
-n 84 48 6 12 re f*
+n 54 72 30 12 re f*
.960784 .960784 .862745 rg
-n 90 48 6 12 re f*
+n 84 72 6 12 re f*
.960784 .960784 .862745 rg
-n 96 48 6 12 re f*
+n 90 72 6 12 re f*
.960784 .960784 .862745 rg
-n 0 36 6 12 re f*
+n 96 72 6 12 re f*
.960784 .960784 .862745 rg
-n 6 36 6 12 re f*
+n 0 60 6 12 re f*
.960784 .960784 .862745 rg
-n 12 36 6 12 re f*
+n 6 60 6 12 re f*
.960784 .960784 .862745 rg
-n 24 36 30 12 re f*
+n 12 60 6 12 re f*
.960784 .960784 .862745 rg
-n 54 36 6 12 re f*
+n 24 60 30 12 re f*
.960784 .960784 .862745 rg
-n 60 36 54 12 re f*
+n 54 60 6 12 re f*
.960784 .960784 .862745 rg
-n 114 36 18 12 re f*
+n 60 60 54 12 re f*
.960784 .960784 .862745 rg
-n 144 36 162 12 re f*
+n 114 60 18 12 re f*
.960784 .960784 .862745 rg
-n 0 24 36 12 re f*
+n 144 60 162 12 re f*
.960784 .960784 .862745 rg
-n 42 24 24 12 re f*
+n 0 48 36 12 re f*
.960784 .960784 .862745 rg
-n 72 24 18 12 re f*
+n 42 48 24 12 re f*
.960784 .960784 .862745 rg
-n 0 0 6 12 re f*
+n 72 48 18 12 re f*
.960784 .960784 .862745 rg
-n 6 0 6 12 re f*
+n 0 24 6 12 re f*
.960784 .960784 .862745 rg
-n 12 0 6 12 re f*
+n 6 24 6 12 re f*
.960784 .960784 .862745 rg
-n 24 0 24 12 re f*
+n 12 24 6 12 re f*
.960784 .960784 .862745 rg
-n 48 0 6 12 re f*
+n 24 24 24 12 re f*
.960784 .960784 .862745 rg
-n 54 0 30 12 re f*
+n 48 24 6 12 re f*
.960784 .960784 .862745 rg
-n 84 0 6 12 re f*
+n 54 24 30 12 re f*
.960784 .960784 .862745 rg
-n 90 0 18 12 re f*
+n 84 24 6 12 re f*
.960784 .960784 .862745 rg
-n 108 0 6 12 re f*
+n 90 24 18 12 re f*
.960784 .960784 .862745 rg
-n 126 0 228 12 re f*
-BT 1 0 0 1 0 194 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj .666667 .133333 1 rg (@blocking) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ("Please wait ...") Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (read_data) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (time) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (sleep) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (3) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# simulate a blocking resource) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("some data") Tj 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (read_data) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# data is not available yet) Tj /F3 10 Tf 0 0 0 rg T* 0 0 0 rg (Please) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (wait) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (...) Tj 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (time) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (sleep) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (read_data) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# data is not available yet) Tj /F3 10 Tf 0 0 0 rg T* 0 0 0 rg (Please) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (wait) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (...) Tj 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (time) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (sleep) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (read_data) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# data is not available yet) Tj /F3 10 Tf 0 0 0 rg T* 0 0 0 rg (Please) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (wait) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (...) Tj 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (time) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (sleep) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1.1) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# after 3.1 seconds, data is available) Tj /F3 10 Tf 0 0 0 rg T* ET
-Q
-Q
-Q
-Q
-Q
-
-endstream
-endobj
-102 0 obj
-<< /Length 17137 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 727.8236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
+n 108 24 6 12 re f*
.960784 .960784 .862745 rg
-n -6 -6 468.6898 36 re B*
-Q
-q
+n 126 24 228 12 re f*
.960784 .960784 .862745 rg
n 0 12 6 12 re f*
.960784 .960784 .862745 rg
@@ -3614,32 +3654,32 @@ n 114 12 18 12 re f*
n 0 0 24 12 re f*
.960784 .960784 .862745 rg
n 30 0 24 12 re f*
-BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (read_data) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* 0 0 0 rg (some) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (data) Tj T* ET
+BT 1 0 0 1 0 218 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj .666667 .133333 1 rg (@blocking) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ("Please wait ...") Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (read_data) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (time) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (sleep) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (3) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# simulate a blocking resource) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("some data") Tj 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (read_data) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# data is not available yet) Tj /F3 10 Tf 0 0 0 rg T* 0 0 0 rg (Please) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (wait) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (...) Tj 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (time) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (sleep) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (read_data) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# data is not available yet) Tj /F3 10 Tf 0 0 0 rg T* 0 0 0 rg (Please) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (wait) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (...) Tj 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (time) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (sleep) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (read_data) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# data is not available yet) Tj /F3 10 Tf 0 0 0 rg T* 0 0 0 rg (Please) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (wait) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (...) Tj 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (time) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (sleep) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1.1) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# after 3.1 seconds, data is available) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (read_data) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* 0 0 0 rg (some) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (data) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 694.8236 cm
+1 0 0 1 62.69291 413.6236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F3 17.5 Tf 0 0 0 rg (decorator\(cls\)) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 664.8236 cm
+1 0 0 1 62.69291 383.6236 cm
q
BT 1 0 0 1 0 14 Tm .441163 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (facility can also produce a decorator starting from a class with the signature of a caller.) Tj T* 0 Tw (In such a case the produced generator is able to convert functions into factories of instances of that class.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 610.8236 cm
+1 0 0 1 62.69291 329.6236 cm
q
BT 1 0 0 1 0 38 Tm 2.853876 Tw 12 TL /F1 10 Tf 0 0 0 rg (As an example, here will I show a decorator which is able to convert a blocking function into an) Tj T* 0 Tw .25811 Tw (asynchronous function. The function, when called, is executed in a separate thread. This is very similar to) Tj T* 0 Tw .453984 Tw (the approach used in the ) Tj /F3 10 Tf 0 0 0 rg (concurrent.futures ) Tj /F1 10 Tf 0 0 0 rg (package. Of course the code here is just an example,) Tj T* 0 Tw (it is not a recommended way of implementing futures. The implementation is the following:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 349.6236 cm
+1 0 0 1 62.69291 92.42362 cm
q
q
1 0 0 1 0 0 cm
@@ -3649,219 +3689,246 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 252 re B*
+n -6 -6 468.6898 228 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 228 30 12 re f*
+n 0 204 30 12 re f*
.960784 .960784 .862745 rg
-n 36 228 36 12 re f*
+n 36 204 36 12 re f*
.960784 .960784 .862745 rg
-n 72 228 6 12 re f*
+n 72 204 6 12 re f*
.960784 .960784 .862745 rg
-n 78 228 54 12 re f*
+n 78 204 54 12 re f*
.960784 .960784 .862745 rg
-n 132 228 6 12 re f*
+n 132 204 6 12 re f*
.960784 .960784 .862745 rg
-n 138 228 36 12 re f*
+n 138 204 36 12 re f*
.960784 .960784 .862745 rg
-n 174 228 12 12 re f*
+n 174 204 12 12 re f*
.960784 .960784 .862745 rg
-n 24 216 18 12 re f*
+n 24 192 18 12 re f*
.960784 .960784 .862745 rg
-n 0 204 354 12 re f*
+n 0 180 354 12 re f*
.960784 .960784 .862745 rg
-n 0 192 186 12 re f*
+n 0 168 186 12 re f*
.960784 .960784 .862745 rg
-n 0 180 42 12 re f*
+n 0 156 42 12 re f*
.960784 .960784 .862745 rg
-n 24 168 18 12 re f*
+n 24 144 18 12 re f*
.960784 .960784 .862745 rg
-n 48 168 48 12 re f*
+n 48 144 48 12 re f*
.960784 .960784 .862745 rg
-n 96 168 6 12 re f*
+n 96 144 6 12 re f*
.960784 .960784 .862745 rg
-n 102 168 24 12 re f*
+n 102 144 24 12 re f*
.960784 .960784 .862745 rg
-n 126 168 6 12 re f*
+n 126 144 6 12 re f*
.960784 .960784 .862745 rg
-n 138 168 24 12 re f*
+n 138 144 24 12 re f*
.960784 .960784 .862745 rg
-n 162 168 6 12 re f*
+n 162 144 6 12 re f*
.960784 .960784 .862745 rg
-n 174 168 6 12 re f*
+n 174 144 6 12 re f*
.960784 .960784 .862745 rg
-n 180 168 24 12 re f*
+n 180 144 24 12 re f*
.960784 .960784 .862745 rg
-n 204 168 6 12 re f*
+n 204 144 6 12 re f*
.960784 .960784 .862745 rg
-n 216 168 12 12 re f*
+n 216 144 12 12 re f*
.960784 .960784 .862745 rg
-n 228 168 12 12 re f*
+n 228 144 12 12 re f*
.960784 .960784 .862745 rg
-n 240 168 12 12 re f*
+n 240 144 12 12 re f*
.960784 .960784 .862745 rg
-n 48 156 18 12 re f*
+n 48 132 18 12 re f*
.960784 .960784 .862745 rg
-n 66 156 6 12 re f*
+n 66 132 6 12 re f*
.960784 .960784 .862745 rg
-n 72 144 42 12 re f*
+n 72 120 42 12 re f*
.960784 .960784 .862745 rg
-n 120 144 6 12 re f*
+n 120 120 6 12 re f*
.960784 .960784 .862745 rg
-n 132 144 24 12 re f*
+n 132 120 24 12 re f*
.960784 .960784 .862745 rg
-n 156 144 6 12 re f*
+n 156 120 6 12 re f*
.960784 .960784 .862745 rg
-n 162 144 42 12 re f*
+n 162 120 42 12 re f*
.960784 .960784 .862745 rg
-n 48 132 36 12 re f*
+n 48 108 36 12 re f*
.960784 .960784 .862745 rg
-n 90 132 84 12 re f*
+n 90 108 84 12 re f*
.960784 .960784 .862745 rg
-n 174 132 6 12 re f*
+n 174 108 6 12 re f*
.960784 .960784 .862745 rg
-n 192 132 258 12 re f*
+n 192 108 258 12 re f*
.960784 .960784 .862745 rg
-n 72 120 42 12 re f*
+n 72 96 42 12 re f*
.960784 .960784 .862745 rg
-n 120 120 6 12 re f*
+n 120 96 6 12 re f*
.960784 .960784 .862745 rg
-n 132 120 24 12 re f*
+n 132 96 24 12 re f*
.960784 .960784 .862745 rg
-n 156 120 6 12 re f*
+n 156 96 6 12 re f*
.960784 .960784 .862745 rg
-n 162 120 42 12 re f*
+n 162 96 42 12 re f*
.960784 .960784 .862745 rg
-n 210 120 6 12 re f*
+n 210 96 6 12 re f*
.960784 .960784 .862745 rg
-n 222 120 54 12 re f*
+n 222 96 54 12 re f*
.960784 .960784 .862745 rg
-n 276 120 6 12 re f*
+n 276 96 6 12 re f*
.960784 .960784 .862745 rg
-n 282 120 30 12 re f*
+n 282 96 30 12 re f*
.960784 .960784 .862745 rg
-n 312 120 6 12 re f*
+n 312 96 6 12 re f*
.960784 .960784 .862745 rg
-n 318 120 6 12 re f*
+n 318 96 6 12 re f*
.960784 .960784 .862745 rg
-n 324 120 6 12 re f*
+n 324 96 6 12 re f*
.960784 .960784 .862745 rg
-n 48 108 24 12 re f*
+n 48 84 24 12 re f*
.960784 .960784 .862745 rg
-n 78 108 6 12 re f*
+n 78 84 6 12 re f*
.960784 .960784 .862745 rg
-n 90 108 6 12 re f*
+n 90 84 6 12 re f*
.960784 .960784 .862745 rg
-n 96 108 12 12 re f*
+n 96 84 12 12 re f*
.960784 .960784 .862745 rg
-n 108 108 6 12 re f*
+n 108 84 6 12 re f*
.960784 .960784 .862745 rg
-n 114 108 12 12 re f*
+n 114 84 12 12 re f*
.960784 .960784 .862745 rg
-n 126 108 6 12 re f*
+n 126 84 6 12 re f*
.960784 .960784 .862745 rg
-n 138 108 6 12 re f*
+n 138 84 6 12 re f*
.960784 .960784 .862745 rg
-n 150 108 6 12 re f*
+n 150 84 6 12 re f*
.960784 .960784 .862745 rg
-n 156 108 24 12 re f*
+n 156 84 24 12 re f*
.960784 .960784 .862745 rg
-n 180 108 6 12 re f*
+n 180 84 6 12 re f*
.960784 .960784 .862745 rg
-n 186 108 48 12 re f*
+n 186 84 48 12 re f*
.960784 .960784 .862745 rg
-n 234 108 6 12 re f*
+n 234 84 6 12 re f*
.960784 .960784 .862745 rg
-n 246 108 24 12 re f*
+n 246 84 24 12 re f*
.960784 .960784 .862745 rg
-n 270 108 6 12 re f*
+n 270 84 6 12 re f*
.960784 .960784 .862745 rg
-n 276 108 42 12 re f*
+n 276 84 42 12 re f*
.960784 .960784 .862745 rg
-n 318 108 12 12 re f*
+n 318 84 12 12 re f*
.960784 .960784 .862745 rg
-n 48 84 18 12 re f*
+n 48 60 18 12 re f*
.960784 .960784 .862745 rg
-n 72 84 72 12 re f*
+n 72 60 72 12 re f*
.960784 .960784 .862745 rg
-n 144 84 18 12 re f*
+n 144 60 18 12 re f*
.960784 .960784 .862745 rg
-n 72 72 24 12 re f*
+n 72 48 24 12 re f*
.960784 .960784 .862745 rg
-n 96 72 6 12 re f*
+n 96 48 6 12 re f*
.960784 .960784 .862745 rg
-n 102 72 42 12 re f*
+n 102 48 42 12 re f*
.960784 .960784 .862745 rg
-n 150 72 6 12 re f*
+n 150 48 6 12 re f*
.960784 .960784 .862745 rg
-n 162 72 24 12 re f*
+n 162 48 24 12 re f*
.960784 .960784 .862745 rg
-n 186 72 6 12 re f*
+n 186 48 6 12 re f*
.960784 .960784 .862745 rg
-n 192 72 6 12 re f*
+n 192 48 6 12 re f*
.960784 .960784 .862745 rg
-n 198 72 24 12 re f*
+n 198 48 24 12 re f*
.960784 .960784 .862745 rg
-n 222 72 6 12 re f*
+n 222 48 6 12 re f*
.960784 .960784 .862745 rg
-n 234 72 12 12 re f*
+n 234 48 12 12 re f*
.960784 .960784 .862745 rg
-n 246 72 12 12 re f*
+n 246 48 12 12 re f*
.960784 .960784 .862745 rg
-n 258 72 6 12 re f*
+n 258 48 6 12 re f*
.960784 .960784 .862745 rg
-n 48 60 30 12 re f*
+n 48 36 30 12 re f*
.960784 .960784 .862745 rg
-n 78 60 6 12 re f*
+n 78 36 6 12 re f*
.960784 .960784 .862745 rg
-n 84 60 36 12 re f*
+n 84 36 36 12 re f*
.960784 .960784 .862745 rg
-n 120 60 6 12 re f*
+n 120 36 6 12 re f*
.960784 .960784 .862745 rg
-n 132 60 24 12 re f*
+n 132 36 24 12 re f*
.960784 .960784 .862745 rg
-n 156 60 6 12 re f*
+n 156 36 6 12 re f*
.960784 .960784 .862745 rg
-n 162 60 6 12 re f*
+n 162 36 6 12 re f*
.960784 .960784 .862745 rg
-n 168 60 48 12 re f*
+n 168 36 48 12 re f*
.960784 .960784 .862745 rg
-n 216 60 6 12 re f*
+n 216 36 6 12 re f*
.960784 .960784 .862745 rg
-n 222 60 36 12 re f*
+n 222 36 36 12 re f*
.960784 .960784 .862745 rg
-n 258 60 6 12 re f*
+n 258 36 6 12 re f*
.960784 .960784 .862745 rg
-n 264 60 72 12 re f*
+n 264 36 72 12 re f*
.960784 .960784 .862745 rg
-n 336 60 6 12 re f*
+n 336 36 6 12 re f*
.960784 .960784 .862745 rg
-n 348 60 24 12 re f*
+n 348 36 24 12 re f*
.960784 .960784 .862745 rg
-n 372 60 6 12 re f*
+n 372 36 6 12 re f*
.960784 .960784 .862745 rg
-n 378 60 24 12 re f*
+n 378 36 24 12 re f*
.960784 .960784 .862745 rg
-n 402 60 6 12 re f*
+n 402 36 6 12 re f*
.960784 .960784 .862745 rg
-n 48 48 24 12 re f*
+n 48 24 24 12 re f*
.960784 .960784 .862745 rg
-n 72 48 6 12 re f*
+n 72 24 6 12 re f*
.960784 .960784 .862745 rg
-n 78 48 30 12 re f*
+n 78 24 30 12 re f*
.960784 .960784 .862745 rg
-n 108 48 12 12 re f*
+n 108 24 12 12 re f*
.960784 .960784 .862745 rg
-n 24 24 18 12 re f*
+n 24 0 18 12 re f*
.960784 .960784 .862745 rg
-n 48 24 36 12 re f*
+n 48 0 36 12 re f*
.960784 .960784 .862745 rg
-n 84 24 6 12 re f*
+n 84 0 6 12 re f*
.960784 .960784 .862745 rg
-n 90 24 24 12 re f*
+n 90 0 24 12 re f*
.960784 .960784 .862745 rg
-n 114 24 12 12 re f*
+n 114 0 12 12 re f*
+BT 1 0 0 1 0 206 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (Future) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (threading) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Thread) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F6 10 Tf .729412 .129412 .129412 rg (""") Tj T* ( A class converting blocking functions into asynchronous) Tj T* ( functions by using threads.) Tj T* ( """) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (__init__) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (try) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (counter) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (counter) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (except) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf .823529 .254902 .227451 rg (AttributeError) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# instantiate the counter at the first call) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj 0 0 0 rg (counter) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (counter) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (itertools) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (count) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (name) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg (') Tj /F5 10 Tf .733333 .4 .533333 rg (%s) Tj /F3 10 Tf .729412 .129412 .129412 rg (-) Tj /F5 10 Tf .733333 .4 .533333 rg (%s) Tj /F3 10 Tf .729412 .129412 .129412 rg (') Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (%) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (\() Tj 0 0 0 rg (func) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (__name__) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (next) Tj 0 0 0 rg (\() Tj 0 0 0 rg (counter) Tj 0 0 0 rg (\)\)) Tj 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (func_wrapper) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (_result) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (super) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Future) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (\)) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (__init__) Tj 0 0 0 rg (\() Tj 0 0 0 rg (target) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg (func_wrapper) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (name) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg (name) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (start) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (result) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+107 0 obj
+<< /Length 14651 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 727.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
.960784 .960784 .862745 rg
n 48 12 24 12 re f*
.960784 .960784 .862745 rg
@@ -3878,20 +3945,20 @@ n 90 0 24 12 re f*
n 114 0 6 12 re f*
.960784 .960784 .862745 rg
n 120 0 42 12 re f*
-BT 1 0 0 1 0 230 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (Future) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (threading) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Thread) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F6 10 Tf .729412 .129412 .129412 rg (""") Tj T* ( A class converting blocking functions into asynchronous) Tj T* ( functions by using threads.) Tj T* ( """) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (__init__) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (try) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (counter) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (counter) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (except) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf .823529 .254902 .227451 rg (AttributeError) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# instantiate the counter at the first call) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj 0 0 0 rg (counter) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (counter) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (itertools) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (count) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (name) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg (') Tj /F5 10 Tf .733333 .4 .533333 rg (%s) Tj /F3 10 Tf .729412 .129412 .129412 rg (-) Tj /F5 10 Tf .733333 .4 .533333 rg (%s) Tj /F3 10 Tf .729412 .129412 .129412 rg (') Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (%) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (\() Tj 0 0 0 rg (func) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (__name__) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (next) Tj 0 0 0 rg (\() Tj 0 0 0 rg (counter) Tj 0 0 0 rg (\)\)) Tj 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (func_wrapper) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (_result) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (super) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Future) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (\)) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (__init__) Tj 0 0 0 rg (\() Tj 0 0 0 rg (target) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg (func_wrapper) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (name) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg (name) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (start) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (result) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (join) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (_result) Tj T* ET
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (join) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (_result) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 317.6236 cm
+1 0 0 1 62.69291 695.8236 cm
q
BT 1 0 0 1 0 14 Tm .143984 Tw 12 TL /F1 10 Tf 0 0 0 rg (The decorated function returns a ) Tj /F3 10 Tf 0 0 0 rg (Future ) Tj /F1 10 Tf 0 0 0 rg (object, which has a ) Tj /F3 10 Tf 0 0 0 rg (.result\(\) ) Tj /F1 10 Tf 0 0 0 rg (method which blocks until the) Tj T* 0 Tw (underlying thread finishes and returns the final result. Here is a minimalistic example of usage:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 176.4236 cm
+1 0 0 1 62.69291 554.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -4033,26 +4100,19 @@ Q
Q
Q
q
-1 0 0 1 62.69291 143.4236 cm
+1 0 0 1 62.69291 521.6236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (contextmanager) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 113.4236 cm
+1 0 0 1 62.69291 491.6236 cm
q
BT 1 0 0 1 0 14 Tm 2.685984 Tw 12 TL /F1 10 Tf 0 0 0 rg (For a long time Python had in its standard library a ) Tj /F3 10 Tf 0 0 0 rg (contextmanager ) Tj /F1 10 Tf 0 0 0 rg (decorator, able to convert) Tj T* 0 Tw (generator functions into ) Tj /F3 10 Tf 0 0 0 rg (GeneratorContextManager ) Tj /F1 10 Tf 0 0 0 rg (factories. For instance if you write) Tj T* ET
Q
Q
-
-endstream
-endobj
-103 0 obj
-<< /Length 12588 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 679.8236 cm
+1 0 0 1 62.69291 398.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -4134,13 +4194,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 647.8236 cm
+1 0 0 1 62.69291 366.4236 cm
q
BT 1 0 0 1 0 14 Tm .150888 Tw 12 TL /F1 10 Tf 0 0 0 rg (then ) Tj /F3 10 Tf 0 0 0 rg (before_after ) Tj /F1 10 Tf 0 0 0 rg (is a factory function returning ) Tj /F3 10 Tf 0 0 0 rg (GeneratorContextManager ) Tj /F1 10 Tf 0 0 0 rg (objects which can be) Tj T* 0 Tw (used with the ) Tj /F3 10 Tf 0 0 0 rg (with ) Tj /F1 10 Tf 0 0 0 rg (statement:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 566.6236 cm
+1 0 0 1 62.69291 285.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -4196,13 +4256,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 522.6236 cm
+1 0 0 1 62.69291 241.2236 cm
q
BT 1 0 0 1 0 26 Tm .462488 Tw 12 TL /F1 10 Tf 0 0 0 rg (Basically, it is as if the content of the ) Tj /F3 10 Tf 0 0 0 rg (with ) Tj /F1 10 Tf 0 0 0 rg (block was executed in the place of the ) Tj /F3 10 Tf 0 0 0 rg (yield ) Tj /F1 10 Tf 0 0 0 rg (expression in) Tj T* 0 Tw 2.691797 Tw (the generator function. In Python 3.2 ) Tj /F3 10 Tf 0 0 0 rg (GeneratorContextManager ) Tj /F1 10 Tf 0 0 0 rg (objects were enhanced with a) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (__call__ ) Tj /F1 10 Tf 0 0 0 rg (method, so that they can be used as decorators as in this example:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 405.4236 cm
+1 0 0 1 62.69291 124.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -4266,31 +4326,44 @@ Q
Q
Q
q
-1 0 0 1 62.69291 277.4236 cm
+1 0 0 1 62.69291 80.02362 cm
+q
+BT 1 0 0 1 0 26 Tm .20561 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F3 10 Tf 0 0 0 rg (ba ) Tj /F1 10 Tf 0 0 0 rg (decorator is basically inserting a ) Tj /F3 10 Tf 0 0 0 rg (with) Tj ( ) Tj (ba: ) Tj /F1 10 Tf 0 0 0 rg (block inside the function. However there two issues: ) Tj T* 0 Tw 1.402126 Tw (the first is that ) Tj /F3 10 Tf 0 0 0 rg (GeneratorContextManager ) Tj /F1 10 Tf 0 0 0 rg (objects are callable only in Python 3.2, so the previous ) Tj T* 0 Tw .356905 Tw (example will break in older versions of Python; the second is that ) Tj /F3 10 Tf 0 0 0 rg (GeneratorContextManager ) Tj /F1 10 Tf 0 0 0 rg (objects) Tj T* 0 Tw ET
+Q
+Q
+
+endstream
+endobj
+108 0 obj
+<< /Length 14222 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 681.0236 cm
q
-BT 1 0 0 1 0 110 Tm .20561 Tw 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F3 10 Tf 0 0 0 rg (ba ) Tj /F1 10 Tf 0 0 0 rg (decorator is basically inserting a ) Tj /F3 10 Tf 0 0 0 rg (with) Tj ( ) Tj (ba: ) Tj /F1 10 Tf 0 0 0 rg (block inside the function. However there two issues:) Tj T* 0 Tw 1.402126 Tw (the first is that ) Tj /F3 10 Tf 0 0 0 rg (GeneratorContextManager ) Tj /F1 10 Tf 0 0 0 rg (objects are callable only in Python 3.2, so the previous) Tj T* 0 Tw .356905 Tw (example will break in older versions of Python; the second is that ) Tj /F3 10 Tf 0 0 0 rg (GeneratorContextManager ) Tj /F1 10 Tf 0 0 0 rg (objects) Tj T* 0 Tw .57561 Tw (do not preserve the signature of the decorated functions: the decorated ) Tj /F3 10 Tf 0 0 0 rg (hello ) Tj /F1 10 Tf 0 0 0 rg (function here will have a) Tj T* 0 Tw 3.990814 Tw (generic signature ) Tj /F3 10 Tf 0 0 0 rg (hello\(*args,) Tj ( ) Tj (**kwargs\) ) Tj /F1 10 Tf 0 0 0 rg (but will break when called with more than zero) Tj T* 0 Tw 7.708314 Tw (arguments. For such reasons the decorator module, starting with release 3.4, offers a) Tj T* 0 Tw 1.027251 Tw /F3 10 Tf 0 0 0 rg (decorator.contextmanager ) Tj /F1 10 Tf 0 0 0 rg (decorator that solves both problems and works in all supported Python) Tj T* 0 Tw 2.85816 Tw (versions. The usage is the same and factories decorated with ) Tj /F3 10 Tf 0 0 0 rg (decorator.contextmanager ) Tj /F1 10 Tf 0 0 0 rg (will) Tj T* 0 Tw .17122 Tw (returns instances of ) Tj /F3 10 Tf 0 0 0 rg (ContextManager) Tj /F1 10 Tf 0 0 0 rg (, a subclass of ) Tj /F3 10 Tf 0 0 0 rg (contextlib.GeneratorContextManager ) Tj /F1 10 Tf 0 0 0 rg (with) Tj T* 0 Tw (a ) Tj /F3 10 Tf 0 0 0 rg (__call__ ) Tj /F1 10 Tf 0 0 0 rg (method acting as a signature-preserving decorator.) Tj T* ET
+BT 1 0 0 1 0 74 Tm .57561 Tw 12 TL /F1 10 Tf 0 0 0 rg (do not preserve the signature of the decorated functions: the decorated ) Tj /F3 10 Tf 0 0 0 rg (hello ) Tj /F1 10 Tf 0 0 0 rg (function here will have a) Tj T* 0 Tw 3.990814 Tw (generic signature ) Tj /F3 10 Tf 0 0 0 rg (hello\(*args,) Tj ( ) Tj (**kwargs\) ) Tj /F1 10 Tf 0 0 0 rg (but will break when called with more than zero) Tj T* 0 Tw 7.708314 Tw (arguments. For such reasons the decorator module, starting with release 3.4, offers a) Tj T* 0 Tw 1.027251 Tw /F3 10 Tf 0 0 0 rg (decorator.contextmanager ) Tj /F1 10 Tf 0 0 0 rg (decorator that solves both problems and works in all supported Python) Tj T* 0 Tw 2.85816 Tw (versions. The usage is the same and factories decorated with ) Tj /F3 10 Tf 0 0 0 rg (decorator.contextmanager ) Tj /F1 10 Tf 0 0 0 rg (will) Tj T* 0 Tw .17122 Tw (returns instances of ) Tj /F3 10 Tf 0 0 0 rg (ContextManager) Tj /F1 10 Tf 0 0 0 rg (, a subclass of ) Tj /F3 10 Tf 0 0 0 rg (contextlib.GeneratorContextManager ) Tj /F1 10 Tf 0 0 0 rg (with) Tj T* 0 Tw (a ) Tj /F3 10 Tf 0 0 0 rg (__call__ ) Tj /F1 10 Tf 0 0 0 rg (method acting as a signature-preserving decorator.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 244.4236 cm
+1 0 0 1 62.69291 648.0236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (The ) Tj /F3 17.5 Tf 0 0 0 rg (FunctionMaker ) Tj /F2 17.5 Tf 0 0 0 rg (class) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 178.4236 cm
+1 0 0 1 62.69291 582.0236 cm
q
BT 1 0 0 1 0 50 Tm 2.241412 Tw 12 TL /F1 10 Tf 0 0 0 rg (You may wonder about how the functionality of the ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (module is implemented. The basic) Tj T* 0 Tw 1.545868 Tw (building block is a ) Tj /F3 10 Tf 0 0 0 rg (FunctionMaker ) Tj /F1 10 Tf 0 0 0 rg (class which is able to generate on the fly functions with a given) Tj T* 0 Tw .047485 Tw (name and signature from a function template passed as a string. Generally speaking, you should not need) Tj T* 0 Tw 1.164983 Tw (to resort to ) Tj /F3 10 Tf 0 0 0 rg (FunctionMaker ) Tj /F1 10 Tf 0 0 0 rg (when writing ordinary decorators, but it is handy in some circumstances.) Tj T* 0 Tw (You will see an example shortly, in the implementation of a cool decorator utility \() Tj /F3 10 Tf 0 0 0 rg (decorator_apply) Tj /F1 10 Tf 0 0 0 rg (\).) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 136.4236 cm
+1 0 0 1 62.69291 540.0236 cm
q
BT 1 0 0 1 0 26 Tm .414597 Tw 12 TL /F3 10 Tf 0 0 0 rg (FunctionMaker ) Tj /F1 10 Tf 0 0 0 rg (provides a ) Tj /F3 10 Tf 0 0 0 rg (.create ) Tj /F1 10 Tf 0 0 0 rg (classmethod which takes as input the name, signature, and body) Tj T* 0 Tw .632927 Tw (of the function we want to generate as well as the execution environment were the function is generated) Tj T* 0 Tw (by ) Tj /F3 10 Tf 0 0 0 rg (exec) Tj /F1 10 Tf 0 0 0 rg (. Here is an example:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 79.22362 cm
+1 0 0 1 62.69291 446.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -4300,76 +4373,49 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
+n -6 -6 468.6898 84 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 24 6 12 re f*
+n 0 60 6 12 re f*
.960784 .960784 .862745 rg
-n 6 24 6 12 re f*
+n 6 60 6 12 re f*
.960784 .960784 .862745 rg
-n 12 24 6 12 re f*
+n 12 60 6 12 re f*
.960784 .960784 .862745 rg
-n 24 24 18 12 re f*
+n 24 60 18 12 re f*
.960784 .960784 .862745 rg
-n 48 24 6 12 re f*
+n 48 60 6 12 re f*
.960784 .960784 .862745 rg
-n 54 24 6 12 re f*
+n 54 60 6 12 re f*
.960784 .960784 .862745 rg
-n 60 24 6 12 re f*
+n 60 60 6 12 re f*
.960784 .960784 .862745 rg
-n 66 24 24 12 re f*
+n 66 60 24 12 re f*
.960784 .960784 .862745 rg
-n 90 24 6 12 re f*
+n 90 60 6 12 re f*
.960784 .960784 .862745 rg
-n 102 24 12 12 re f*
+n 102 60 12 12 re f*
.960784 .960784 .862745 rg
-n 114 24 12 12 re f*
+n 114 60 12 12 re f*
.960784 .960784 .862745 rg
-n 126 24 12 12 re f*
+n 126 60 12 12 re f*
.960784 .960784 .862745 rg
-n 144 24 222 12 re f*
+n 144 60 222 12 re f*
.960784 .960784 .862745 rg
-n 0 12 18 12 re f*
+n 0 48 18 12 re f*
.960784 .960784 .862745 rg
-n 48 12 30 12 re f*
+n 48 48 30 12 re f*
.960784 .960784 .862745 rg
-n 78 12 6 12 re f*
+n 78 48 6 12 re f*
.960784 .960784 .862745 rg
-n 84 12 24 12 re f*
+n 84 48 24 12 re f*
.960784 .960784 .862745 rg
-n 108 12 6 12 re f*
+n 108 48 6 12 re f*
.960784 .960784 .862745 rg
-n 120 12 12 12 re f*
+n 120 48 12 12 re f*
.960784 .960784 .862745 rg
-n 132 12 6 12 re f*
-BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (f) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\):) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# a function with a generic signature) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* T* ET
-Q
-Q
-Q
-Q
-Q
-
-endstream
-endobj
-104 0 obj
-<< /Length 16944 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 715.8236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
-Q
-q
+n 132 48 6 12 re f*
.960784 .960784 .862745 rg
n 0 24 6 12 re f*
.960784 .960784 .862745 rg
@@ -4438,32 +4484,32 @@ n 24 0 6 12 re f*
n 30 0 6 12 re f*
.960784 .960784 .862745 rg
n 42 0 12 12 re f*
-BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f1) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (FunctionMaker) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (create) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('f1\(a, b\)') Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ('f\(a, b\)') Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (dict) Tj 0 0 0 rg (\() Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg (f) Tj 0 0 0 rg (\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f1) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (,) Tj .4 .4 .4 rg (2) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (2) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj 0 0 0 rg ({}) Tj T* ET
+BT 1 0 0 1 0 62 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (f) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\):) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# a function with a generic signature) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f1) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (FunctionMaker) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (create) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('f1\(a, b\)') Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ('f\(a, b\)') Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (dict) Tj 0 0 0 rg (\() Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg (f) Tj 0 0 0 rg (\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f1) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (,) Tj .4 .4 .4 rg (2) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* 0 0 0 rg (\() Tj .4 .4 .4 rg (1) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (2) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj 0 0 0 rg ({}) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 683.8236 cm
+1 0 0 1 62.69291 414.8236 cm
q
BT 1 0 0 1 0 14 Tm .226654 Tw 12 TL /F1 10 Tf 0 0 0 rg (It is important to notice that the function body is interpolated before being executed, so be careful with the) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (% ) Tj /F1 10 Tf 0 0 0 rg (sign!) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 641.8236 cm
+1 0 0 1 62.69291 372.8236 cm
q
BT 1 0 0 1 0 26 Tm 1.995433 Tw 12 TL /F3 10 Tf 0 0 0 rg (FunctionMaker.create ) Tj /F1 10 Tf 0 0 0 rg (also accepts keyword arguments and such arguments are attached to the) Tj T* 0 Tw 1.64686 Tw (resulting function. This is useful if you want to set some function attributes, for instance the docstring) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (__doc__) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 599.8236 cm
+1 0 0 1 62.69291 330.8236 cm
q
BT 1 0 0 1 0 26 Tm .605318 Tw 12 TL /F1 10 Tf 0 0 0 rg (For debugging/introspection purposes it may be useful to see the source code of the generated function;) Tj T* 0 Tw 2.246235 Tw (to do that, just pass the flag ) Tj /F3 10 Tf 0 0 0 rg (addsource=True ) Tj /F1 10 Tf 0 0 0 rg (and a ) Tj /F3 10 Tf 0 0 0 rg (__source__ ) Tj /F1 10 Tf 0 0 0 rg (attribute will be added to the) Tj T* 0 Tw (generated function:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 506.6236 cm
+1 0 0 1 62.69291 237.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -4581,25 +4627,32 @@ Q
Q
Q
q
-1 0 0 1 62.69291 366.6236 cm
+1 0 0 1 62.69291 97.62362 cm
q
BT 1 0 0 1 0 122 Tm .870651 Tw 12 TL /F3 10 Tf 0 0 0 rg (FunctionMaker.create ) Tj /F1 10 Tf 0 0 0 rg (can take as first argument a string, as in the examples before, or a function.) Tj T* 0 Tw .224985 Tw (This is the most common usage, since typically you want to decorate a pre-existing function. A framework) Tj T* 0 Tw 1.606136 Tw (author may want to use directly ) Tj /F3 10 Tf 0 0 0 rg (FunctionMaker.create ) Tj /F1 10 Tf 0 0 0 rg (instead of ) Tj /F3 10 Tf 0 0 0 rg (decorator) Tj /F1 10 Tf 0 0 0 rg (, since it gives you) Tj T* 0 Tw 1.36686 Tw (direct access to the body of the generated function. For instance, suppose you want to instrument the) Tj T* 0 Tw .372209 Tw /F3 10 Tf 0 0 0 rg (__init__ ) Tj /F1 10 Tf 0 0 0 rg (methods of a set of classes, by preserving their signature \(such use case is not made up; this) Tj T* 0 Tw .673828 Tw (is done in SQAlchemy and in other frameworks\). When the first argument of ) Tj /F3 10 Tf 0 0 0 rg (FunctionMaker.create) Tj T* 0 Tw 3.405814 Tw /F1 10 Tf 0 0 0 rg (is a function, a ) Tj /F3 10 Tf 0 0 0 rg (FunctionMaker ) Tj /F1 10 Tf 0 0 0 rg (object is instantiated internally, with attributes ) Tj /F3 10 Tf 0 0 0 rg (args) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F3 10 Tf 0 0 0 rg (varargs) Tj /F1 10 Tf 0 0 0 rg (,) Tj T* 0 Tw 5.509982 Tw /F3 10 Tf 0 0 0 rg (keywords ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (defaults ) Tj /F1 10 Tf 0 0 0 rg (which are the the return values of the standard library function) Tj T* 0 Tw .561318 Tw /F3 10 Tf 0 0 0 rg (inspect.getargspec) Tj /F1 10 Tf 0 0 0 rg (. For each argument in the ) Tj /F3 10 Tf 0 0 0 rg (args ) Tj /F1 10 Tf 0 0 0 rg (\(which is a list of strings containing the names) Tj T* 0 Tw 1.599985 Tw (of the mandatory arguments\) an attribute ) Tj /F3 10 Tf 0 0 0 rg (arg0) Tj /F1 10 Tf 0 0 0 rg (, ) Tj /F3 10 Tf 0 0 0 rg (arg1) Tj /F1 10 Tf 0 0 0 rg (, ..., ) Tj /F3 10 Tf 0 0 0 rg (argN ) Tj /F1 10 Tf 0 0 0 rg (is also generated. Finally, there is a) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (signature ) Tj /F1 10 Tf 0 0 0 rg (attribute, a string with the signature of the original function.) Tj T* ET
Q
Q
+
+endstream
+endobj
+109 0 obj
+<< /Length 16271 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 333.6236 cm
+1 0 0 1 62.69291 744.0236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Getting the source code) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 255.6236 cm
+1 0 0 1 62.69291 666.0236 cm
q
BT 1 0 0 1 0 62 Tm 5.045529 Tw 12 TL /F1 10 Tf 0 0 0 rg (Internally ) Tj /F3 10 Tf 0 0 0 rg (FunctionMaker.create ) Tj /F1 10 Tf 0 0 0 rg (uses ) Tj /F3 10 Tf 0 0 0 rg (exec ) Tj /F1 10 Tf 0 0 0 rg (to generate the decorated function. Therefore) Tj T* 0 Tw 2.542126 Tw /F3 10 Tf 0 0 0 rg (inspect.getsource ) Tj /F1 10 Tf 0 0 0 rg (will not work for decorated functions. That means that the usual '??' trick in) Tj T* 0 Tw 26.45775 Tw (IPython will give you the \(right on the spot\) message) Tj T* 0 Tw .261647 Tw /F3 10 Tf 0 0 0 rg (Dynamically) Tj ( ) Tj (generated) Tj ( ) Tj (function.) Tj ( ) Tj (No) Tj ( ) Tj (source) Tj ( ) Tj (code available) Tj /F1 10 Tf 0 0 0 rg (. In the past I have considered) Tj T* 0 Tw .945366 Tw (this acceptable, since ) Tj /F3 10 Tf 0 0 0 rg (inspect.getsource ) Tj /F1 10 Tf 0 0 0 rg (does not really work even with regular decorators. In that) Tj T* 0 Tw (case ) Tj /F3 10 Tf 0 0 0 rg (inspect.getsource ) Tj /F1 10 Tf 0 0 0 rg (gives you the wrapper source code which is probably not what you want:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 186.4236 cm
+1 0 0 1 62.69291 596.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -4669,7 +4722,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 141.2236 cm
+1 0 0 1 62.69291 551.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -4725,7 +4778,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 84.02362 cm
+1 0 0 1 62.69291 470.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -4735,86 +4788,59 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
+n -6 -6 468.6898 72 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 24 6 12 re f*
-.960784 .960784 .862745 rg
-n 6 24 6 12 re f*
+n 0 48 6 12 re f*
.960784 .960784 .862745 rg
-n 12 24 6 12 re f*
+n 6 48 6 12 re f*
.960784 .960784 .862745 rg
-n 24 24 36 12 re f*
+n 12 48 6 12 re f*
.960784 .960784 .862745 rg
-n 66 24 42 12 re f*
+n 24 48 36 12 re f*
.960784 .960784 .862745 rg
-n 0 12 6 12 re f*
+n 66 48 42 12 re f*
.960784 .960784 .862745 rg
-n 6 12 6 12 re f*
+n 0 36 6 12 re f*
.960784 .960784 .862745 rg
-n 12 12 6 12 re f*
+n 6 36 6 12 re f*
.960784 .960784 .862745 rg
-n 24 12 30 12 re f*
+n 12 36 6 12 re f*
.960784 .960784 .862745 rg
-n 54 12 6 12 re f*
+n 24 36 30 12 re f*
.960784 .960784 .862745 rg
-n 60 12 42 12 re f*
+n 54 36 6 12 re f*
.960784 .960784 .862745 rg
-n 102 12 6 12 re f*
+n 60 36 42 12 re f*
.960784 .960784 .862745 rg
-n 108 12 54 12 re f*
+n 102 36 6 12 re f*
.960784 .960784 .862745 rg
-n 162 12 6 12 re f*
+n 108 36 54 12 re f*
.960784 .960784 .862745 rg
-n 168 12 42 12 re f*
+n 162 36 6 12 re f*
.960784 .960784 .862745 rg
-n 210 12 12 12 re f*
+n 168 36 42 12 re f*
.960784 .960784 .862745 rg
-n 24 0 18 12 re f*
+n 210 36 12 12 re f*
.960784 .960784 .862745 rg
-n 48 0 42 12 re f*
+n 24 24 18 12 re f*
.960784 .960784 .862745 rg
-n 90 0 6 12 re f*
+n 48 24 42 12 re f*
.960784 .960784 .862745 rg
-n 96 0 6 12 re f*
+n 90 24 6 12 re f*
.960784 .960784 .862745 rg
-n 102 0 24 12 re f*
+n 96 24 6 12 re f*
.960784 .960784 .862745 rg
-n 126 0 6 12 re f*
+n 102 24 24 12 re f*
.960784 .960784 .862745 rg
-n 138 0 12 12 re f*
+n 126 24 6 12 re f*
.960784 .960784 .862745 rg
-n 150 0 12 12 re f*
+n 138 24 12 12 re f*
.960784 .960784 .862745 rg
-n 162 0 12 12 re f*
-BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (import) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (inspect) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (inspect) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (getsource) Tj 0 0 0 rg (\() Tj 0 0 0 rg (example) Tj 0 0 0 rg (\)\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (wrapper) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ET
-Q
-Q
-Q
-Q
-Q
-
-endstream
-endobj
-105 0 obj
-<< /Length 13449 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 727.8236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
+n 150 24 12 12 re f*
.960784 .960784 .862745 rg
-n -6 -6 468.6898 36 re B*
-Q
-q
+n 162 24 12 12 re f*
.960784 .960784 .862745 rg
n 48 12 36 12 re f*
.960784 .960784 .862745 rg
@@ -4839,20 +4865,20 @@ n 0 0 6 12 re f*
n 6 0 54 12 re f*
.960784 .960784 .862745 rg
n 60 0 6 12 re f*
-BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (<) Tj 0 0 0 rg (BLANKLINE) Tj .4 .4 .4 rg (>) Tj T* ET
+BT 1 0 0 1 0 50 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (import) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (inspect) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (inspect) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (getsource) Tj 0 0 0 rg (\() Tj 0 0 0 rg (example) Tj 0 0 0 rg (\)\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (wrapper) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kw) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (<) Tj 0 0 0 rg (BLANKLINE) Tj .4 .4 .4 rg (>) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 671.8236 cm
+1 0 0 1 62.69291 414.4236 cm
q
-BT 1 0 0 1 0 38 Tm 1.471235 Tw 12 TL /F1 10 Tf 0 0 0 rg (\(see bug report ) Tj 0 0 .501961 rg (1764286 ) Tj 0 0 0 rg (for an explanation of what is happening\). Unfortunately the bug is still there,) Tj T* 0 Tw .508409 Tw (even in Python 2.7 and 3.4 \(it will be fixed for Python 3.5, thought\). There is however a workaround. The) Tj T* 0 Tw .325984 Tw (decorated function has an attribute ) Tj /F3 10 Tf 0 0 0 rg (.__wrapped__) Tj /F1 10 Tf 0 0 0 rg (, pointing to the original function. The easy way to get) Tj T* 0 Tw (the source code is to call ) Tj /F3 10 Tf 0 0 0 rg (inspect.getsource ) Tj /F1 10 Tf 0 0 0 rg (on the undecorated function:) Tj T* ET
+BT 1 0 0 1 0 38 Tm .011098 Tw 12 TL /F1 10 Tf 0 0 0 rg (\(see bug report ) Tj 0 0 .501961 rg (1764286 ) Tj 0 0 0 rg (for an explanation of what is happening\). Unfortunately the bug is still there, in all) Tj T* 0 Tw 1.33436 Tw (versions of Python except Python 3.5, which is not yet released. There is however a workaround. The) Tj T* 0 Tw .325984 Tw (decorated function has an attribute ) Tj /F3 10 Tf 0 0 0 rg (.__wrapped__) Tj /F1 10 Tf 0 0 0 rg (, pointing to the original function. The easy way to get) Tj T* 0 Tw (the source code is to call ) Tj /F3 10 Tf 0 0 0 rg (inspect.getsource ) Tj /F1 10 Tf 0 0 0 rg (on the undecorated function:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 554.6236 cm
+1 0 0 1 62.69291 297.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -4962,19 +4988,19 @@ Q
Q
Q
q
-1 0 0 1 62.69291 521.6236 cm
+1 0 0 1 62.69291 264.2236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Dealing with third party decorators) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 467.6236 cm
+1 0 0 1 62.69291 210.2236 cm
q
BT 1 0 0 1 0 38 Tm .321654 Tw 12 TL /F1 10 Tf 0 0 0 rg (Sometimes you find on the net some cool decorator that you would like to include in your code. However,) Tj T* 0 Tw .50061 Tw (more often than not the cool decorator is not signature-preserving. Therefore you may want an easy way) Tj T* 0 Tw 1.814597 Tw (to upgrade third party decorators to signature-preserving decorators without having to rewrite them in) Tj T* 0 Tw (terms of ) Tj /F3 10 Tf 0 0 0 rg (decorator) Tj /F1 10 Tf 0 0 0 rg (. You can use a ) Tj /F3 10 Tf 0 0 0 rg (FunctionMaker ) Tj /F1 10 Tf 0 0 0 rg (to implement that functionality as follows:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 350.4236 cm
+1 0 0 1 62.69291 93.02362 cm
q
q
1 0 0 1 0 0 cm
@@ -5061,26 +5087,33 @@ Q
Q
Q
Q
+
+endstream
+endobj
+110 0 obj
+<< /Length 16103 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 318.4236 cm
+1 0 0 1 62.69291 741.0236 cm
q
BT 1 0 0 1 0 14 Tm .698314 Tw 12 TL /F3 10 Tf 0 0 0 rg (decorator_apply ) Tj /F1 10 Tf 0 0 0 rg (sets the attribute ) Tj /F3 10 Tf 0 0 0 rg (.__wrapped__ ) Tj /F1 10 Tf 0 0 0 rg (of the generated function to the original function,) Tj T* 0 Tw (so that you can get the right source code.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 276.4236 cm
+1 0 0 1 62.69291 699.0236 cm
q
BT 1 0 0 1 0 26 Tm .13104 Tw 12 TL /F1 10 Tf 0 0 0 rg (Notice that I am not providing this functionality in the ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (module directly since I think it is best to) Tj T* 0 Tw 2.070751 Tw (rewrite the decorator rather than adding an additional level of indirection. However, practicality beats) Tj T* 0 Tw (purity, so you can add ) Tj /F3 10 Tf 0 0 0 rg (decorator_apply ) Tj /F1 10 Tf 0 0 0 rg (to your toolbox and use it if you need to.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 222.4236 cm
+1 0 0 1 62.69291 645.0236 cm
q
BT 1 0 0 1 0 38 Tm 1.74881 Tw 12 TL /F1 10 Tf 0 0 0 rg (In order to give an example of usage of ) Tj /F3 10 Tf 0 0 0 rg (decorator_apply) Tj /F1 10 Tf 0 0 0 rg (, I will show a pretty slick decorator that) Tj T* 0 Tw 1.276651 Tw (converts a tail-recursive function in an iterative function. I have shamelessly stolen the basic idea from) Tj T* 0 Tw 43.62829 Tw (Kay Schluehr's recipe in the Python Cookbook,) Tj T* 0 Tw 0 0 .501961 rg (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496691) Tj 0 0 0 rg (.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 81.22362 cm
+1 0 0 1 62.69291 275.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -5090,90 +5123,63 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 132 re B*
+n -6 -6 468.6898 360 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 108 30 12 re f*
+n 0 336 30 12 re f*
.960784 .960784 .862745 rg
-n 36 108 78 12 re f*
+n 36 336 78 12 re f*
.960784 .960784 .862745 rg
-n 114 108 6 12 re f*
+n 114 336 6 12 re f*
.960784 .960784 .862745 rg
-n 120 108 36 12 re f*
+n 120 336 36 12 re f*
.960784 .960784 .862745 rg
-n 156 108 12 12 re f*
+n 156 336 12 12 re f*
.960784 .960784 .862745 rg
-n 24 96 18 12 re f*
+n 24 324 18 12 re f*
.960784 .960784 .862745 rg
-n 0 84 354 12 re f*
+n 0 312 354 12 re f*
.960784 .960784 .862745 rg
-n 0 72 396 12 re f*
+n 0 300 396 12 re f*
.960784 .960784 .862745 rg
-n 0 60 276 12 re f*
+n 0 288 276 12 re f*
.960784 .960784 .862745 rg
-n 0 48 42 12 re f*
+n 0 276 42 12 re f*
.960784 .960784 .862745 rg
-n 24 24 18 12 re f*
+n 24 252 18 12 re f*
.960784 .960784 .862745 rg
-n 48 24 48 12 re f*
+n 48 252 48 12 re f*
.960784 .960784 .862745 rg
-n 96 24 6 12 re f*
+n 96 252 6 12 re f*
.960784 .960784 .862745 rg
-n 102 24 24 12 re f*
+n 102 252 24 12 re f*
.960784 .960784 .862745 rg
-n 126 24 6 12 re f*
+n 126 252 6 12 re f*
.960784 .960784 .862745 rg
-n 138 24 24 12 re f*
+n 138 252 24 12 re f*
.960784 .960784 .862745 rg
-n 162 24 12 12 re f*
+n 162 252 12 12 re f*
.960784 .960784 .862745 rg
-n 48 12 24 12 re f*
+n 48 240 24 12 re f*
.960784 .960784 .862745 rg
-n 72 12 6 12 re f*
+n 72 240 6 12 re f*
.960784 .960784 .862745 rg
-n 78 12 24 12 re f*
+n 78 240 24 12 re f*
.960784 .960784 .862745 rg
-n 108 12 6 12 re f*
+n 108 240 6 12 re f*
.960784 .960784 .862745 rg
-n 120 12 24 12 re f*
+n 120 240 24 12 re f*
.960784 .960784 .862745 rg
-n 48 0 24 12 re f*
+n 48 228 24 12 re f*
.960784 .960784 .862745 rg
-n 72 0 6 12 re f*
-.960784 .960784 .862745 rg
-n 78 0 54 12 re f*
+n 72 228 6 12 re f*
.960784 .960784 .862745 rg
-n 138 0 6 12 re f*
+n 78 228 54 12 re f*
.960784 .960784 .862745 rg
-n 150 0 24 12 re f*
-BT 1 0 0 1 0 110 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (TailRecursive) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F6 10 Tf .729412 .129412 .129412 rg (""") Tj T* ( tail_recursive decorator based on Kay Schluehr's recipe) Tj T* ( http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496691) Tj T* ( with improvements by me and George Sakkis.) Tj T* ( """) Tj /F3 10 Tf 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (__init__) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (func) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (firstcall) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (True) Tj 0 0 0 rg T* ET
-Q
-Q
-Q
-Q
-Q
-
-endstream
-endobj
-106 0 obj
-<< /Length 16122 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 523.8236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
+n 138 228 6 12 re f*
.960784 .960784 .862745 rg
-n -6 -6 468.6898 240 re B*
-Q
-q
+n 150 228 24 12 re f*
.960784 .960784 .862745 rg
n 48 216 24 12 re f*
.960784 .960784 .862745 rg
@@ -5354,21 +5360,21 @@ n 198 12 18 12 re f*
n 72 0 36 12 re f*
.960784 .960784 .862745 rg
n 114 0 48 12 re f*
-BT 1 0 0 1 0 218 Tm 12 TL /F3 10 Tf 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (CONTINUE) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# sentinel) Tj /F3 10 Tf 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (__call__) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kwd) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (CONTINUE) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (CONTINUE) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (if) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (firstcall) Tj 0 0 0 rg (:) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (func) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (firstcall) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (False) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (try) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (while) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 .501961 0 rg (True) Tj 0 0 0 rg (:) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (result) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kwd) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (if) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (result) Tj 0 0 0 rg ( ) Tj /F5 10 Tf .666667 .133333 1 rg (is) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (CONTINUE) Tj 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# update arguments) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (kwd) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (argskwd) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (else) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# last call) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (result) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (finally) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (firstcall) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (True) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (else) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# return the arguments of the tail call) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (argskwd) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (kwd) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (CONTINUE) Tj T* ET
+BT 1 0 0 1 0 338 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (TailRecursive) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F6 10 Tf .729412 .129412 .129412 rg (""") Tj T* ( tail_recursive decorator based on Kay Schluehr's recipe) Tj T* ( http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496691) Tj T* ( with improvements by me and George Sakkis.) Tj T* ( """) Tj /F3 10 Tf 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (__init__) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (func) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (firstcall) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (True) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (CONTINUE) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# sentinel) Tj /F3 10 Tf 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (__call__) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kwd) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (CONTINUE) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (CONTINUE) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (if) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (firstcall) Tj 0 0 0 rg (:) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (func) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (firstcall) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (False) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (try) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (while) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 .501961 0 rg (True) Tj 0 0 0 rg (:) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (result) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (func) Tj 0 0 0 rg (\() Tj .4 .4 .4 rg (*) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (**) Tj 0 0 0 rg (kwd) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (if) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (result) Tj 0 0 0 rg ( ) Tj /F5 10 Tf .666667 .133333 1 rg (is) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (CONTINUE) Tj 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# update arguments) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (kwd) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (argskwd) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (else) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# last call) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (result) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (finally) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (firstcall) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (True) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (else) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# return the arguments of the tail call) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj 0 .501961 0 rg (self) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (argskwd) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (args) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (kwd) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (CONTINUE) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 503.8236 cm
+1 0 0 1 62.69291 255.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Here the decorator is implemented as a class returning callable objects.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 458.6236 cm
+1 0 0 1 62.69291 210.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -5412,14 +5418,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 438.6236 cm
+1 0 0 1 62.69291 190.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Here is how you apply the upgraded decorator to the good old factorial:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 345.4236 cm
+1 0 0 1 62.69291 97.42362 cm
q
q
1 0 0 1 0 0 cm
@@ -5496,8 +5502,15 @@ Q
Q
Q
Q
+
+endstream
+endobj
+111 0 obj
+<< /Length 13654 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 300.2236 cm
+1 0 0 1 62.69291 727.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -5537,13 +5550,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 244.2236 cm
+1 0 0 1 62.69291 671.8236 cm
q
BT 1 0 0 1 0 38 Tm .188935 Tw 12 TL /F1 10 Tf 0 0 0 rg (This decorator is pretty impressive, and should give you some food for your mind ;\) Notice that there is no) Tj T* 0 Tw 1.339983 Tw (recursion limit now, and you can easily compute ) Tj /F3 10 Tf 0 0 0 rg (factorial\(1001\) ) Tj /F1 10 Tf 0 0 0 rg (or larger without filling the stack) Tj T* 0 Tw .909431 Tw (frame. Notice also that the decorator will not work on functions which are not tail recursive, such as the) Tj T* 0 Tw (following) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 175.0236 cm
+1 0 0 1 62.69291 602.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -5607,39 +5620,32 @@ Q
Q
Q
q
-1 0 0 1 62.69291 143.0236 cm
+1 0 0 1 62.69291 570.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .541098 Tw (\(reminder: a function is tail recursive if it either returns a value without making a recursive call, or returns) Tj T* 0 Tw (directly the result of a recursive call\).) Tj T* ET
Q
Q
-
-endstream
-endobj
-107 0 obj
-<< /Length 13031 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 744.0236 cm
+1 0 0 1 62.69291 537.6236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Multiple dispatch) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 654.0236 cm
+1 0 0 1 62.69291 447.6236 cm
q
-BT 1 0 0 1 0 74 Tm .11936 Tw 12 TL /F1 10 Tf 0 0 0 rg (There has been talk of implementing multiple dispatch \(i.e. generic\) functions in Python for over ten years.) Tj T* 0 Tw 3.96881 Tw (Last year for the first time something was done and now in Python 3.4 we have a decorator) Tj T* 0 Tw 1.049269 Tw /F4 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (which can be used to implement generic functions. As the name implies, it has) Tj T* 0 Tw 1.474198 Tw (the restriction of being limited to single dispatch, i.e. it is able to dispatch on the first argument of the) Tj T* 0 Tw 2.516412 Tw (function only. The decorator module provide a decorator factory ) Tj /F4 10 Tf 0 0 0 rg (dispatch_on ) Tj /F1 10 Tf 0 0 0 rg (which can be used to) Tj T* 0 Tw .616905 Tw (implement generic functions dispatching on any argument; moreover it can manage dispatching on more) Tj T* 0 Tw (than one argument and, of course, it is signature-preserving.) Tj T* ET
+BT 1 0 0 1 0 74 Tm .11936 Tw 12 TL /F1 10 Tf 0 0 0 rg (There has been talk of implementing multiple dispatch \(i.e. generic\) functions in Python for over ten years.) Tj T* 0 Tw 3.96881 Tw (Last year for the first time something was done and now in Python 3.4 we have a decorator) Tj T* 0 Tw .294147 Tw /F3 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (which can be used to implement generic functions. As the name implies,) Tj T* 0 Tw .063322 Tw (it has the restriction of being limited to single dispatch, i.e. it is able to dispatch on the first argument of the) Tj T* 0 Tw 1.423555 Tw (function only. The decorator module provide a decorator factory ) Tj /F3 10 Tf 0 0 0 rg (dispatch_on ) Tj /F1 10 Tf 0 0 0 rg (which can be used to) Tj T* 0 Tw .616905 Tw (implement generic functions dispatching on any argument; moreover it can manage dispatching on more) Tj T* 0 Tw (than one argument and, of course, it is signature-preserving.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 612.0236 cm
+1 0 0 1 62.69291 405.6236 cm
q
-BT 1 0 0 1 0 26 Tm 1.551163 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here I will give a very concrete example where it is desiderable to dispatch on the second argument.) Tj T* 0 Tw .216412 Tw (Suppose you have an XMLWriter class, which is instantiated with some configuration parameters and has) Tj T* 0 Tw (a ) Tj /F4 10 Tf 0 0 0 rg (.write ) Tj /F1 10 Tf 0 0 0 rg (method which is able to serialize objects to XML:) Tj T* ET
+BT 1 0 0 1 0 26 Tm 1.551163 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here I will give a very concrete example where it is desiderable to dispatch on the second argument.) Tj T* 0 Tw .216412 Tw (Suppose you have an XMLWriter class, which is instantiated with some configuration parameters and has) Tj T* 0 Tw (a ) Tj /F3 10 Tf 0 0 0 rg (.write ) Tj /F1 10 Tf 0 0 0 rg (method which is able to serialize objects to XML:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 506.8236 cm
+1 0 0 1 62.69291 300.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -5731,13 +5737,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 426.8236 cm
+1 0 0 1 62.69291 220.4236 cm
q
-BT 1 0 0 1 0 62 Tm .502927 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here you want to dispatch on the second argument since the first, ) Tj /F4 10 Tf 0 0 0 rg (self ) Tj /F1 10 Tf 0 0 0 rg (is already taken. The ) Tj /F4 10 Tf 0 0 0 rg (dispatch_on) Tj T* 0 Tw .817209 Tw /F1 10 Tf 0 0 0 rg (facility allows you to specify the dispatch argument by simply passing its name as a string \(notice that if) Tj T* 0 Tw 1.681163 Tw (you mispell the name you will get an error\). The function decorated with ) Tj /F4 10 Tf 0 0 0 rg (dispatch_on ) Tj /F1 10 Tf 0 0 0 rg (is turned into a) Tj T* 0 Tw .145868 Tw (generic function and it is the one which is called if there are no more specialized implementations. Usually) Tj T* 0 Tw 4.188314 Tw (such default function should raise a ) Tj /F4 10 Tf 0 0 0 rg (NotImplementedError) Tj /F1 10 Tf 0 0 0 rg (, thus forcing people to register some) Tj T* 0 Tw (implementation. The registration can be done with a decorator:) Tj T* ET
+BT 1 0 0 1 0 62 Tm 3.34936 Tw 12 TL /F1 10 Tf 0 0 0 rg (Here you want to dispatch on the second argument since the first, ) Tj /F3 10 Tf 0 0 0 rg (self ) Tj /F1 10 Tf 0 0 0 rg (is already taken. The) Tj T* 0 Tw 1.127485 Tw /F4 10 Tf 0 0 0 rg (dispatch_on ) Tj /F1 10 Tf 0 0 0 rg (facility allows you to specify the dispatch argument by simply passing its name as a string) Tj T* 0 Tw 1.583516 Tw (\(notice that if you mispell the name you will get an error\). The function decorated with ) Tj /F4 10 Tf 0 0 0 rg (dispatch_on ) Tj /F1 10 Tf 0 0 0 rg (is) Tj T* 0 Tw 3.223876 Tw (turned into a generic function and it is the one which is called if there are no more specialized) Tj T* 0 Tw 2.518976 Tw (implementations. Usually such default function should raise a ) Tj /F3 10 Tf 0 0 0 rg (NotImplementedError) Tj /F1 10 Tf 0 0 0 rg (, thus forcing) Tj T* 0 Tw (people to register some implementation. The registration can be done with a decorator:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 369.6236 cm
+1 0 0 1 62.69291 163.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -5803,14 +5809,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 349.6236 cm
+1 0 0 1 62.69291 143.2236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Now the XMLWriter is able to serialize floats:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 292.4236 cm
+1 0 0 1 62.69291 86.02362 cm
q
q
1 0 0 1 0 0 cm
@@ -5879,15 +5885,22 @@ Q
Q
Q
Q
+
+endstream
+endobj
+112 0 obj
+<< /Length 16060 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 236.4236 cm
+1 0 0 1 62.69291 717.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL .352209 Tw (I could give a down-to-earth example of situations in which it is desiderable to dispatch on more than one) Tj T* 0 Tw 3.67998 Tw (argument \(for instance once I implemented a database-access library where the first dispatching) Tj T* 0 Tw .164987 Tw (argument was the the database driver and the second the database record\), but here I prefer to follow the) Tj T* 0 Tw (tradition and show the time-honored Rock-Paper-Scissor example:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 191.2236 cm
+1 0 0 1 62.69291 671.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -5923,7 +5936,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 146.0236 cm
+1 0 0 1 62.69291 626.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -5959,7 +5972,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 100.8236 cm
+1 0 0 1 62.69291 581.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -5994,21 +6007,14 @@ Q
Q
Q
Q
-
-endstream
-endobj
-108 0 obj
-<< /Length 17039 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 681.0236 cm
+1 0 0 1 62.69291 489.4236 cm
q
-BT 1 0 0 1 0 74 Tm .606235 Tw 12 TL /F1 10 Tf 0 0 0 rg (I have added an ordinal to the Rock-Paper-Scissor classes to simplify the implementation. The idea is to) Tj T* 0 Tw .764692 Tw (define a generic function ) Tj /F4 10 Tf 0 0 0 rg (win\(a, b\) ) Tj /F1 10 Tf 0 0 0 rg (of two arguments corresponding to the moves of the first and second) Tj T* 0 Tw .721984 Tw (player respectively. The moves are instances of the classes Rock, Paper and Scissors; Paper wins over) Tj T* 0 Tw .528488 Tw (Rock, Scissor wins over Paper and Rock wins over Scissor. The function will return +1 for a win, -1 for a) Tj T* 0 Tw 1.578735 Tw (loss and 0 for parity. There are 9 combinations, however combinations with the same ordinal \(i.e. the) Tj T* 0 Tw .438221 Tw (same class\) return 0; moreover by exchanging the order of the arguments the sign of the result changes,) Tj T* 0 Tw (so it is enough to specify directly only 3 implementations:) Tj T* ET
+BT 1 0 0 1 0 74 Tm .606235 Tw 12 TL /F1 10 Tf 0 0 0 rg (I have added an ordinal to the Rock-Paper-Scissor classes to simplify the implementation. The idea is to) Tj T* 0 Tw 1.821235 Tw (define a generic function ) Tj /F3 10 Tf 0 0 0 rg (win\(a, b\) ) Tj /F1 10 Tf 0 0 0 rg (of two arguments corresponding to the moves of the first and) Tj T* 0 Tw 1.487126 Tw (second player respectively. The moves are instances of the classes Rock, Paper and Scissors; Paper) Tj T* 0 Tw .00104 Tw (wins over Rock, Scissor wins over Paper and Rock wins over Scissor. The function will return +1 for a win,) Tj T* 0 Tw .415542 Tw (-1 for a loss and 0 for parity. There are 9 combinations, however combinations with the same ordinal \(i.e.) Tj T* 0 Tw 2.007633 Tw (the same class\) return 0; moreover by exchanging the order of the arguments the sign of the result) Tj T* 0 Tw (changes, so it is enough to specify directly only 3 implementations:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 575.8236 cm
+1 0 0 1 62.69291 384.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -6132,7 +6138,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 518.6236 cm
+1 0 0 1 62.69291 327.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -6184,7 +6190,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 461.4236 cm
+1 0 0 1 62.69291 269.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -6236,7 +6242,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 404.2236 cm
+1 0 0 1 62.69291 212.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -6286,14 +6292,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 384.2236 cm
+1 0 0 1 62.69291 192.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Here is the result:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 147.0236 cm
+1 0 0 1 62.69291 87.42362 cm
q
q
1 0 0 1 0 0 cm
@@ -6303,87 +6309,114 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 228 re B*
+n -6 -6 468.6898 96 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 204 6 12 re f*
+n 0 72 6 12 re f*
.960784 .960784 .862745 rg
-n 6 204 6 12 re f*
+n 6 72 6 12 re f*
.960784 .960784 .862745 rg
-n 12 204 6 12 re f*
+n 12 72 6 12 re f*
.960784 .960784 .862745 rg
-n 24 204 18 12 re f*
+n 24 72 18 12 re f*
.960784 .960784 .862745 rg
-n 42 204 6 12 re f*
+n 42 72 6 12 re f*
.960784 .960784 .862745 rg
-n 48 204 30 12 re f*
+n 48 72 30 12 re f*
.960784 .960784 .862745 rg
-n 78 204 18 12 re f*
+n 78 72 18 12 re f*
.960784 .960784 .862745 rg
-n 102 204 24 12 re f*
+n 102 72 24 12 re f*
.960784 .960784 .862745 rg
-n 126 204 18 12 re f*
+n 126 72 18 12 re f*
.960784 .960784 .862745 rg
-n 0 192 6 12 re f*
+n 0 60 6 12 re f*
.960784 .960784 .862745 rg
-n 0 180 6 12 re f*
+n 0 48 6 12 re f*
.960784 .960784 .862745 rg
-n 6 180 6 12 re f*
+n 6 48 6 12 re f*
.960784 .960784 .862745 rg
-n 12 180 6 12 re f*
+n 12 48 6 12 re f*
.960784 .960784 .862745 rg
-n 24 180 18 12 re f*
+n 24 48 18 12 re f*
.960784 .960784 .862745 rg
-n 42 180 6 12 re f*
+n 42 48 6 12 re f*
.960784 .960784 .862745 rg
-n 48 180 42 12 re f*
+n 48 48 42 12 re f*
.960784 .960784 .862745 rg
-n 90 180 18 12 re f*
+n 90 48 18 12 re f*
.960784 .960784 .862745 rg
-n 114 180 30 12 re f*
+n 114 48 30 12 re f*
.960784 .960784 .862745 rg
-n 144 180 18 12 re f*
+n 144 48 18 12 re f*
.960784 .960784 .862745 rg
-n 0 168 6 12 re f*
+n 0 36 6 12 re f*
.960784 .960784 .862745 rg
-n 0 156 6 12 re f*
+n 0 24 6 12 re f*
.960784 .960784 .862745 rg
-n 6 156 6 12 re f*
+n 6 24 6 12 re f*
.960784 .960784 .862745 rg
-n 12 156 6 12 re f*
+n 12 24 6 12 re f*
.960784 .960784 .862745 rg
-n 24 156 18 12 re f*
+n 24 24 18 12 re f*
.960784 .960784 .862745 rg
-n 42 156 6 12 re f*
+n 42 24 6 12 re f*
.960784 .960784 .862745 rg
-n 48 156 24 12 re f*
+n 48 24 24 12 re f*
.960784 .960784 .862745 rg
-n 72 156 18 12 re f*
+n 72 24 18 12 re f*
.960784 .960784 .862745 rg
-n 96 156 42 12 re f*
+n 96 24 42 12 re f*
.960784 .960784 .862745 rg
-n 138 156 18 12 re f*
+n 138 24 18 12 re f*
.960784 .960784 .862745 rg
-n 0 144 6 12 re f*
+n 0 12 6 12 re f*
.960784 .960784 .862745 rg
-n 0 132 6 12 re f*
+n 0 0 6 12 re f*
.960784 .960784 .862745 rg
-n 6 132 6 12 re f*
+n 6 0 6 12 re f*
.960784 .960784 .862745 rg
-n 12 132 6 12 re f*
+n 12 0 6 12 re f*
.960784 .960784 .862745 rg
-n 24 132 18 12 re f*
+n 24 0 18 12 re f*
.960784 .960784 .862745 rg
-n 42 132 6 12 re f*
+n 42 0 6 12 re f*
.960784 .960784 .862745 rg
-n 48 132 30 12 re f*
+n 48 0 30 12 re f*
.960784 .960784 .862745 rg
-n 78 132 18 12 re f*
+n 78 0 18 12 re f*
.960784 .960784 .862745 rg
-n 102 132 30 12 re f*
+n 102 0 30 12 re f*
.960784 .960784 .862745 rg
-n 132 132 18 12 re f*
+n 132 0 18 12 re f*
+BT 1 0 0 1 0 74 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+113 0 obj
+<< /Length 13036 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 619.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 144 re B*
+Q
+q
.960784 .960784 .862745 rg
n 0 120 6 12 re f*
.960784 .960784 .862745 rg
@@ -6492,28 +6525,27 @@ n 138 12 18 12 re f*
n 0 0 6 12 re f*
.960784 .960784 .862745 rg
n 6 0 6 12 re f*
-BT 1 0 0 1 0 206 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj T* ET
+BT 1 0 0 1 0 122 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Paper) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (win) Tj 0 0 0 rg (\() Tj 0 0 0 rg (Scissor) Tj 0 0 0 rg (\(\),) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (Rock) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (-) Tj .4 .4 .4 rg (1) Tj T* ET
+Q
Q
Q
Q
Q
+q
+1 0 0 1 62.69291 586.8236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Generics and Abstract Base Classes) Tj T* ET
+Q
Q
q
-1 0 0 1 62.69291 115.0236 cm
+1 0 0 1 62.69291 556.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .840751 Tw (Generic functions implementations in Python are complicated by the existence of "virtual ancestors", i.e.) Tj T* 0 Tw (superclasses which are not in the class hierarchy. Consider for instance this class:) Tj T* ET
Q
Q
-
-endstream
-endobj
-109 0 obj
-<< /Length 7650 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 715.8236 cm
+1 0 0 1 62.69291 499.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -6533,9 +6565,13 @@ n 36 24 60 12 re f*
.960784 .960784 .862745 rg
n 96 24 6 12 re f*
.960784 .960784 .862745 rg
-n 102 24 36 12 re f*
+n 102 24 66 12 re f*
.960784 .960784 .862745 rg
-n 138 24 12 12 re f*
+n 168 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 174 24 30 12 re f*
+.960784 .960784 .862745 rg
+n 204 24 12 12 re f*
.960784 .960784 .862745 rg
n 24 12 18 12 re f*
.960784 .960784 .862745 rg
@@ -6550,20 +6586,20 @@ n 120 12 12 12 re f*
n 48 0 36 12 re f*
.960784 .960784 .862745 rg
n 90 0 6 12 re f*
-BT 1 0 0 1 0 26 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (WithLength) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (__len__) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .4 .4 .4 rg (0) Tj T* ET
+BT 1 0 0 1 0 26 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (WithLength) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (collections) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Sized) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (__len__) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (self) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .4 .4 .4 rg (0) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 683.8236 cm
+1 0 0 1 62.69291 467.6236 cm
q
-BT 1 0 0 1 0 14 Tm 1.30832 Tw 12 TL /F1 10 Tf 0 0 0 rg (This class defines a ) Tj /F4 10 Tf 0 0 0 rg (__len__ ) Tj /F1 10 Tf 0 0 0 rg (method and as such is considered to be a subclass of the abstract base) Tj T* 0 Tw (class ) Tj /F4 10 Tf 0 0 0 rg (Sized) Tj /F1 10 Tf 0 0 0 rg (:) Tj T* ET
+BT 1 0 0 1 0 14 Tm .772765 Tw 12 TL /F1 10 Tf 0 0 0 rg (This class defines a ) Tj /F3 10 Tf 0 0 0 rg (__len__ ) Tj /F1 10 Tf 0 0 0 rg (method and as such is considered to be a subclass of the abstract base) Tj T* 0 Tw (class ) Tj /F3 10 Tf 0 0 0 rg (Sized) Tj /F1 10 Tf 0 0 0 rg (:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 638.6236 cm
+1 0 0 1 62.69291 422.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -6576,27 +6612,51 @@ q
n -6 -6 468.6898 36 re B*
Q
q
-BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( issubclass\(WithLength, collections.Sized\)) Tj T* (True) Tj T* ET
+.960784 .960784 .862745 rg
+n 0 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 6 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 12 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 12 60 12 re f*
+.960784 .960784 .862745 rg
+n 84 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 90 12 60 12 re f*
+.960784 .960784 .862745 rg
+n 150 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 162 12 66 12 re f*
+.960784 .960784 .862745 rg
+n 228 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 234 12 30 12 re f*
+.960784 .960784 .862745 rg
+n 264 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 0 0 24 12 re f*
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 .501961 0 rg (issubclass) Tj 0 0 0 rg (\() Tj 0 0 0 rg (WithLength) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (collections) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Sized) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* 0 .501961 0 rg (True) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 606.6236 cm
+1 0 0 1 62.69291 378.4236 cm
q
-BT 1 0 0 1 0 14 Tm 1.548314 Tw 12 TL /F1 10 Tf 0 0 0 rg (However, ) Tj /F4 10 Tf 0 0 0 rg (collections.Sized ) Tj /F1 10 Tf 0 0 0 rg (is not an ancestor of ) Tj /F4 10 Tf 0 0 0 rg (WithLenght) Tj /F1 10 Tf 0 0 0 rg (. Any implementation of generic functions,) Tj T* 0 Tw (even with single dispatch, must go through some contorsion to take into account the virtual ancestors.) Tj T* ET
+BT 1 0 0 1 0 26 Tm 2.180888 Tw 12 TL /F1 10 Tf 0 0 0 rg (However, ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized ) Tj /F1 10 Tf 0 0 0 rg (is not an ancestor of ) Tj /F3 10 Tf 0 0 0 rg (WithLenght) Tj /F1 10 Tf 0 0 0 rg (. Any implementation of generic) Tj T* 0 Tw 1.570651 Tw (functions, even with single dispatch, must go through some contorsion to take into account the virtual) Tj T* 0 Tw (ancestors.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 588.6236 cm
+1 0 0 1 62.69291 360.4236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (In particular if we define a generic function) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 531.4236 cm
+1 0 0 1 62.69291 303.2236 cm
q
q
1 0 0 1 0 0 cm
@@ -6648,14 +6708,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 511.4236 cm
+1 0 0 1 62.69291 283.2236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (implemented on all classes with a lenght) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 454.2236 cm
+1 0 0 1 62.69291 226.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -6707,13 +6767,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 434.2236 cm
+1 0 0 1 62.69291 206.0236 cm
q
-BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (then ) Tj /F4 10 Tf 0 0 0 rg (get_length ) Tj /F1 10 Tf 0 0 0 rg (must be defined on ) Tj /F4 10 Tf 0 0 0 rg (WithLength ) Tj /F1 10 Tf 0 0 0 rg (instances:) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (then ) Tj /F3 10 Tf 0 0 0 rg (get_length ) Tj /F1 10 Tf 0 0 0 rg (must be defined on ) Tj /F3 10 Tf 0 0 0 rg (WithLength ) Tj /F1 10 Tf 0 0 0 rg (instances:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 389.0236 cm
+1 0 0 1 62.69291 160.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -6726,34 +6786,103 @@ q
n -6 -6 468.6898 36 re B*
Q
q
-BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj (>) Tj (>) Tj ( get_length\(WithLength\(\)\)) Tj T* (0) Tj T* ET
+.960784 .960784 .862745 rg
+n 0 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 6 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 12 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 12 60 12 re f*
+.960784 .960784 .862745 rg
+n 84 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 90 12 60 12 re f*
+.960784 .960784 .862745 rg
+n 150 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 0 0 6 12 re f*
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (get_length) Tj 0 0 0 rg (\() Tj 0 0 0 rg (WithLength) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 345.0236 cm
+1 0 0 1 62.69291 140.8236 cm
q
-0 0 0 rg
-BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 1.208555 Tw (The implementation of generic functions in the decorator module is marked as experimental because it) Tj T* 0 Tw .122488 Tw (may fail in some corner cases. Also, the implementation does not even attempt to use a cache, so it is not) Tj T* 0 Tw (as fast as it could be. Simplicity was the paramount concern of this implementation.) Tj T* ET
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Of course this is a contrived example since you could just use the builtin ) Tj /F3 10 Tf 0 0 0 rg (len) Tj /F1 10 Tf 0 0 0 rg (, but you should get the idea.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 312.0236 cm
+1 0 0 1 62.69291 86.82362 cm
q
-BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Caveats and limitations) Tj T* ET
+BT 1 0 0 1 0 38 Tm 1.208555 Tw 12 TL /F1 10 Tf 0 0 0 rg (The implementation of generic functions in the decorator module is marked as experimental because it) Tj T* 0 Tw 9.424147 Tw (may change in the future. Simplicity was preferred over consistency with the way) Tj T* 0 Tw 4.854976 Tw /F3 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (works in the standard library. For instance, suppose we define) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (WithLength ) Tj /F1 10 Tf 0 0 0 rg (as a virtual subclass of ) Tj /F3 10 Tf 0 0 0 rg (collections.Set) Tj /F1 10 Tf 0 0 0 rg (:) Tj T* ET
Q
Q
+
+endstream
+endobj
+114 0 obj
+<< /Length 7359 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 282.0236 cm
+1 0 0 1 62.69291 739.8236 cm
q
-0 0 0 rg
-BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .474987 Tw (The first thing you should be aware of, it the fact that decorators have a performance penalty. The worse) Tj T* 0 Tw (case is shown by the following example:) Tj T* ET
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+.960784 .960784 .862745 rg
+n 0 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 6 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 12 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 36 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 48 0 66 12 re f*
+.960784 .960784 .862745 rg
+n 114 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 120 0 18 12 re f*
+.960784 .960784 .862745 rg
+n 138 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 144 0 48 12 re f*
+.960784 .960784 .862745 rg
+n 192 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 198 0 60 12 re f*
+.960784 .960784 .862745 rg
+n 258 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 276 0 174 12 re f*
+BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (_) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (collections) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Set) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (WithLength) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# issubclass\(WithLength, Set\)) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 719.8236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Now, let us define an implementation of ) Tj /F3 10 Tf 0 0 0 rg (get_length ) Tj /F1 10 Tf 0 0 0 rg (specific to set:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 80.82362 cm
+1 0 0 1 62.69291 662.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -6763,25 +6892,59 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 192 re B*
+n -6 -6 468.6898 48 re B*
Q
q
-0 0 0 rg
-BT 1 0 0 1 0 170 Tm /F3 10 Tf 12 TL ($ cat performance.sh) Tj T* (python3 -m timeit -s ") Tj T* (from decorator import decorator) Tj T* T* (@decorator) Tj T* (def do_nothing\(func, *args, **kw\):) Tj T* ( return func\(*args, **kw\)) Tj T* T* (@do_nothing) Tj T* (def f\(\):) Tj T* ( pass) Tj T* (" "f\(\)") Tj T* T* (python3 -m timeit -s ") Tj T* (def f\(\):) Tj T* ET
+.960784 .960784 .862745 rg
+n 0 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 6 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 12 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 24 120 12 re f*
+.960784 .960784 .862745 rg
+n 144 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 150 24 66 12 re f*
+.960784 .960784 .862745 rg
+n 216 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 222 24 18 12 re f*
+.960784 .960784 .862745 rg
+n 240 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 0 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 24 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 48 12 84 12 re f*
+.960784 .960784 .862745 rg
+n 132 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 138 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 156 12 12 12 re f*
+.960784 .960784 .862745 rg
+n 0 0 18 12 re f*
+.960784 .960784 .862745 rg
+n 48 0 36 12 re f*
+.960784 .960784 .862745 rg
+n 90 0 6 12 re f*
+BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj .666667 .133333 1 rg (@get_length.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (collections) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Set) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (get_length_set) Tj 0 0 0 rg (\() Tj 0 0 0 rg (obj) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .4 .4 .4 rg (1) Tj T* ET
Q
Q
Q
Q
Q
-
-endstream
-endobj
-110 0 obj
-<< /Length 12555 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 727.8236 cm
+1 0 0 1 62.69291 630.6236 cm
+q
+BT 1 0 0 1 0 14 Tm 2.462651 Tw 12 TL /F1 10 Tf 0 0 0 rg (The current implementation first check in the MRO and then look for abstract bases classes; since) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (WithLength ) Tj /F1 10 Tf 0 0 0 rg (inherits directly from ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized ) Tj /F1 10 Tf 0 0 0 rg (that implementation is found first:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 585.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -6794,21 +6957,82 @@ q
n -6 -6 468.6898 36 re B*
Q
q
+.960784 .960784 .862745 rg
+n 0 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 6 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 12 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 12 60 12 re f*
+.960784 .960784 .862745 rg
+n 84 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 90 12 60 12 re f*
+.960784 .960784 .862745 rg
+n 150 12 18 12 re f*
+.960784 .960784 .862745 rg
+n 0 0 6 12 re f*
+BT 1 0 0 1 0 14 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (get_length) Tj 0 0 0 rg (\() Tj 0 0 0 rg (WithLength) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (0) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 541.4236 cm
+q
+BT 1 0 0 1 0 26 Tm 2.257752 Tw 12 TL /F1 10 Tf 0 0 0 rg (Generic functions implemented via ) Tj /F3 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (use a more sophisticated lookup) Tj T* 0 Tw 1.095542 Tw (algorithm; in particular they are able to discern that a ) Tj /F3 10 Tf 0 0 0 rg (Set ) Tj /F1 10 Tf 0 0 0 rg (is a ) Tj /F3 10 Tf 0 0 0 rg (Sized ) Tj /F1 10 Tf 0 0 0 rg (object, so the most specialized) Tj T* 0 Tw (implementation is the one for ) Tj /F3 10 Tf 0 0 0 rg (Set ) Tj /F1 10 Tf 0 0 0 rg (and the result should be 1, not 0.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 511.4236 cm
+q
+BT 1 0 0 1 0 14 Tm 2.653735 Tw 12 TL /F1 10 Tf 0 0 0 rg (Finally let me notice that the current implementation does not use any cache, whereas the one in) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (singledispatch ) Tj /F1 10 Tf 0 0 0 rg (has a cache.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 478.4236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Caveats and limitations) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 448.4236 cm
+q
0 0 0 rg
-BT 1 0 0 1 0 14 Tm /F3 10 Tf 12 TL ( pass) Tj T* (" "f\(\)") Tj T* ET
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .474987 Tw (The first thing you should be aware of, it the fact that decorators have a performance penalty. The worse) Tj T* 0 Tw (case is shown by the following example:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 223.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 216 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 194 Tm /F3 10 Tf 12 TL ($ cat performance.sh) Tj T* (python3 -m timeit -s ") Tj T* (from decorator import decorator) Tj T* T* (@decorator) Tj T* (def do_nothing\(func, *args, **kw\):) Tj T* ( return func\(*args, **kw\)) Tj T* T* (@do_nothing) Tj T* (def f\(\):) Tj T* ( pass) Tj T* (" "f\(\)") Tj T* T* (python3 -m timeit -s ") Tj T* (def f\(\):) Tj T* ( pass) Tj T* (" "f\(\)") Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 707.8236 cm
+1 0 0 1 62.69291 203.2236 cm
q
BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (On my laptop, using the ) Tj /F3 10 Tf 0 0 0 rg (do_nothing ) Tj /F1 10 Tf 0 0 0 rg (decorator instead of the plain function is five times slower:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 650.6236 cm
+1 0 0 1 62.69291 146.0236 cm
q
q
1 0 0 1 0 0 cm
@@ -6829,20 +7053,27 @@ Q
Q
Q
q
-1 0 0 1 62.69291 606.6236 cm
+1 0 0 1 62.69291 102.0236 cm
q
BT 1 0 0 1 0 26 Tm 1.25832 Tw 12 TL /F1 10 Tf 0 0 0 rg (It should be noted that a real life function would probably do something more useful than ) Tj /F3 10 Tf 0 0 0 rg (f ) Tj /F1 10 Tf 0 0 0 rg (here, and) Tj T* 0 Tw .91811 Tw (therefore in real life the performance penalty could be completely negligible. As always, the only way to) Tj T* 0 Tw (know if there is a penalty in your specific use case is to measure it.) Tj T* ET
Q
Q
+
+endstream
+endobj
+115 0 obj
+<< /Length 16053 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 576.6236 cm
+1 0 0 1 62.69291 741.0236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .867984 Tw (You should be aware that decorators will make your tracebacks longer and more difficult to understand.) Tj T* 0 Tw (Consider this example:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 519.4236 cm
+1 0 0 1 62.69291 683.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -6886,13 +7117,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 487.4236 cm
+1 0 0 1 62.69291 651.8236 cm
q
BT 1 0 0 1 0 14 Tm .583318 Tw 12 TL /F1 10 Tf 0 0 0 rg (Calling ) Tj /F3 10 Tf 0 0 0 rg (f\(\) ) Tj /F1 10 Tf 0 0 0 rg (will give you a ) Tj /F3 10 Tf 0 0 0 rg (ZeroDivisionError) Tj /F1 10 Tf 0 0 0 rg (, but since the function is decorated the traceback will) Tj T* 0 Tw (be longer:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 358.2236 cm
+1 0 0 1 62.69291 522.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -7040,31 +7271,31 @@ Q
Q
Q
q
-1 0 0 1 62.69291 290.2236 cm
+1 0 0 1 62.69291 454.6236 cm
q
BT 1 0 0 1 0 50 Tm 1.05528 Tw 12 TL /F1 10 Tf 0 0 0 rg (You see here the inner call to the decorator ) Tj /F3 10 Tf 0 0 0 rg (trace) Tj /F1 10 Tf 0 0 0 rg (, which calls ) Tj /F3 10 Tf 0 0 0 rg (f\(*args,) Tj ( ) Tj (**kw\)) Tj /F1 10 Tf 0 0 0 rg (, and a reference to) Tj T* 0 Tw .076457 Tw /F3 10 Tf 0 0 0 rg (File) Tj ( ) Tj (") Tj (<) Tj (string) Tj (>) Tj (",) Tj ( ) Tj (line) Tj ( ) Tj (2,) Tj ( ) Tj (in) Tj ( ) Tj (f) Tj /F1 10 Tf 0 0 0 rg (. This latter reference is due to the fact that internally the decorator) Tj T* 0 Tw 2.053318 Tw (module uses ) Tj /F3 10 Tf 0 0 0 rg (exec ) Tj /F1 10 Tf 0 0 0 rg (to generate the decorated function. Notice that ) Tj /F3 10 Tf 0 0 0 rg (exec ) Tj /F1 10 Tf 0 0 0 rg (is ) Tj /F4 10 Tf (not ) Tj /F1 10 Tf (responsibile for the) Tj T* 0 Tw 1.507485 Tw (performance penalty, since is the called ) Tj /F4 10 Tf (only once ) Tj /F1 10 Tf (at function decoration time, and not every time the) Tj T* 0 Tw (decorated function is called.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 212.2236 cm
+1 0 0 1 62.69291 376.6236 cm
q
BT 1 0 0 1 0 62 Tm .932209 Tw 12 TL /F1 10 Tf 0 0 0 rg (At present, there is no clean way to avoid ) Tj /F3 10 Tf 0 0 0 rg (exec) Tj /F1 10 Tf 0 0 0 rg (. A clean solution would require to change the CPython) Tj T* 0 Tw .777485 Tw (implementation of functions and add an hook to make it possible to change their signature directly. That) Tj T* 0 Tw .74186 Tw (could happen in future versions of Python \(see PEP ) Tj 0 0 .501961 rg (362) Tj 0 0 0 rg (\) and then the decorator module would become) Tj T* 0 Tw 2.385318 Tw (obsolete. However, at present, even in Python 3.5 it is impossible to change the function signature) Tj T* 0 Tw 1.372485 Tw (directly, therefore the ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (module is still useful. Actually, this is the main reasons why I keep) Tj T* 0 Tw (maintaining the module and releasing new versions.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 170.2236 cm
+1 0 0 1 62.69291 334.6236 cm
q
-BT 1 0 0 1 0 26 Tm 1.043828 Tw 12 TL /F1 10 Tf 0 0 0 rg (In the present implementation, decorators generated by ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (can only be used on user-defined) Tj T* 0 Tw .152485 Tw (Python functions or methods, not on generic callable objects, nor on built-in functions, due to limitations of) Tj T* 0 Tw (the ) Tj /F3 10 Tf 0 0 0 rg (inspect ) Tj /F1 10 Tf 0 0 0 rg (module in the standard library.) Tj T* ET
+BT 1 0 0 1 0 26 Tm 1.043828 Tw 12 TL /F1 10 Tf 0 0 0 rg (In the present implementation, decorators generated by ) Tj /F3 10 Tf 0 0 0 rg (decorator ) Tj /F1 10 Tf 0 0 0 rg (can only be used on user-defined) Tj T* 0 Tw .152485 Tw (Python functions or methods, not on generic callable objects, nor on built-in functions, due to limitations of) Tj T* 0 Tw (the ) Tj /F3 10 Tf 0 0 0 rg (inspect ) Tj /F1 10 Tf 0 0 0 rg (module in the standard library, especially for Python 2.X.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 140.2236 cm
+1 0 0 1 62.69291 304.6236 cm
q
BT 1 0 0 1 0 14 Tm .785777 Tw 12 TL /F1 10 Tf 0 0 0 rg (There is a restriction on the names of the arguments: for instance, if try to call an argument ) Tj /F3 10 Tf 0 0 0 rg (_call_ ) Tj /F1 10 Tf 0 0 0 rg (or) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (_func_ ) Tj /F1 10 Tf 0 0 0 rg (you will get a ) Tj /F3 10 Tf 0 0 0 rg (NameError) Tj /F1 10 Tf 0 0 0 rg (:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 83.02362 cm
+1 0 0 1 62.69291 187.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -7074,66 +7305,39 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 48 re B*
+n -6 -6 468.6898 108 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 24 6 12 re f*
+n 0 84 6 12 re f*
.960784 .960784 .862745 rg
-n 6 24 6 12 re f*
+n 6 84 6 12 re f*
.960784 .960784 .862745 rg
-n 12 24 6 12 re f*
+n 12 84 6 12 re f*
.960784 .960784 .862745 rg
-n 24 24 36 12 re f*
+n 24 84 36 12 re f*
.960784 .960784 .862745 rg
-n 0 12 18 12 re f*
+n 0 72 18 12 re f*
.960784 .960784 .862745 rg
-n 24 12 18 12 re f*
+n 24 72 18 12 re f*
.960784 .960784 .862745 rg
-n 48 12 6 12 re f*
+n 48 72 6 12 re f*
.960784 .960784 .862745 rg
-n 54 12 6 12 re f*
+n 54 72 6 12 re f*
.960784 .960784 .862745 rg
-n 60 12 36 12 re f*
+n 60 72 36 12 re f*
.960784 .960784 .862745 rg
-n 96 12 12 12 re f*
+n 96 72 12 12 re f*
.960784 .960784 .862745 rg
-n 114 12 30 12 re f*
+n 114 72 30 12 re f*
.960784 .960784 .862745 rg
-n 144 12 6 12 re f*
+n 144 72 6 12 re f*
.960784 .960784 .862745 rg
-n 150 12 6 12 re f*
+n 150 72 6 12 re f*
.960784 .960784 .862745 rg
-n 156 12 6 12 re f*
+n 156 72 6 12 re f*
.960784 .960784 .862745 rg
-n 0 0 18 12 re f*
-BT 1 0 0 1 0 26 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj .666667 .133333 1 rg (@trace) Tj 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (f) Tj 0 0 0 rg (\() Tj 0 0 0 rg (_func_) Tj 0 0 0 rg (\):) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (f) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg T* ET
-Q
-Q
-Q
-Q
-Q
-
-endstream
-endobj
-111 0 obj
-<< /Length 10448 >>
-stream
-1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
-q
-1 0 0 1 62.69291 691.8236 cm
-q
-q
-1 0 0 1 0 0 cm
-q
-1 0 0 1 6.6 6.6 cm
-q
-.662745 .662745 .662745 RG
-.5 w
-.960784 .960784 .862745 rg
-n -6 -6 468.6898 72 re B*
-Q
-q
+n 0 60 18 12 re f*
.960784 .960784 .862745 rg
n 0 48 54 12 re f*
.960784 .960784 .862745 rg
@@ -7186,21 +7390,21 @@ n 144 0 6 12 re f*
n 156 0 36 12 re f*
.960784 .960784 .862745 rg
n 192 0 6 12 re f*
-BT 1 0 0 1 0 50 Tm 12 TL /F3 10 Tf 0 0 0 rg (Traceback) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (\() Tj 0 0 0 rg (most) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (recent) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (call) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (last) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj .4 .4 .4 rg (...) Tj 0 0 0 rg T* /F5 10 Tf .823529 .254902 .227451 rg (NameError) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (_func_) Tj 0 0 0 rg ( ) Tj /F5 10 Tf .666667 .133333 1 rg (is) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (overridden) Tj 0 0 0 rg ( ) Tj /F5 10 Tf .666667 .133333 1 rg (in) Tj /F3 10 Tf 0 0 0 rg T* /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (f) Tj 0 0 0 rg (\() Tj 0 0 0 rg (_func_) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (_call_) Tj 0 0 0 rg (\() Tj 0 0 0 rg (_func_) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (_func_) Tj 0 0 0 rg (\)) Tj T* ET
+BT 1 0 0 1 0 86 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj .666667 .133333 1 rg (@trace) Tj 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (f) Tj 0 0 0 rg (\() Tj 0 0 0 rg (_func_) Tj 0 0 0 rg (\):) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (print) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (f) Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* .4 .4 .4 rg (...) Tj 0 0 0 rg T* 0 0 0 rg (Traceback) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (\() Tj 0 0 0 rg (most) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (recent) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (call) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (last) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj .4 .4 .4 rg (...) Tj 0 0 0 rg T* /F5 10 Tf .823529 .254902 .227451 rg (NameError) Tj /F3 10 Tf 0 0 0 rg (:) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (_func_) Tj 0 0 0 rg ( ) Tj /F5 10 Tf .666667 .133333 1 rg (is) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (overridden) Tj 0 0 0 rg ( ) Tj /F5 10 Tf .666667 .133333 1 rg (in) Tj /F3 10 Tf 0 0 0 rg T* /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (f) Tj 0 0 0 rg (\() Tj 0 0 0 rg (_func_) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (_call_) Tj 0 0 0 rg (\() Tj 0 0 0 rg (_func_) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (_func_) Tj 0 0 0 rg (\)) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 659.8236 cm
+1 0 0 1 62.69291 155.4236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.720651 Tw (Finally, the implementation is such that the decorated function makes a \(shallow\) copy of the original) Tj T* 0 Tw (function dictionary:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 506.6236 cm
+1 0 0 1 62.69291 86.22362 cm
q
q
1 0 0 1 0 0 cm
@@ -7210,61 +7414,88 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 144 re B*
+n -6 -6 468.6898 60 re B*
Q
q
.960784 .960784 .862745 rg
-n 0 120 6 12 re f*
+n 0 36 6 12 re f*
.960784 .960784 .862745 rg
-n 6 120 6 12 re f*
+n 6 36 6 12 re f*
.960784 .960784 .862745 rg
-n 12 120 6 12 re f*
+n 12 36 6 12 re f*
.960784 .960784 .862745 rg
-n 24 120 18 12 re f*
+n 24 36 18 12 re f*
.960784 .960784 .862745 rg
-n 48 120 6 12 re f*
+n 48 36 6 12 re f*
.960784 .960784 .862745 rg
-n 54 120 18 12 re f*
+n 54 36 18 12 re f*
.960784 .960784 .862745 rg
-n 78 120 24 12 re f*
+n 78 36 24 12 re f*
.960784 .960784 .862745 rg
-n 108 120 138 12 re f*
+n 108 36 138 12 re f*
.960784 .960784 .862745 rg
-n 0 108 6 12 re f*
+n 0 24 6 12 re f*
.960784 .960784 .862745 rg
-n 6 108 6 12 re f*
+n 6 24 6 12 re f*
.960784 .960784 .862745 rg
-n 12 108 6 12 re f*
+n 12 24 6 12 re f*
.960784 .960784 .862745 rg
-n 24 108 6 12 re f*
+n 24 24 6 12 re f*
.960784 .960784 .862745 rg
-n 30 108 6 12 re f*
+n 30 24 6 12 re f*
.960784 .960784 .862745 rg
-n 36 108 30 12 re f*
+n 36 24 30 12 re f*
.960784 .960784 .862745 rg
-n 72 108 6 12 re f*
+n 72 24 6 12 re f*
.960784 .960784 .862745 rg
-n 84 108 66 12 re f*
+n 84 24 66 12 re f*
.960784 .960784 .862745 rg
-n 156 108 132 12 re f*
+n 156 24 132 12 re f*
.960784 .960784 .862745 rg
-n 0 96 6 12 re f*
+n 0 12 6 12 re f*
.960784 .960784 .862745 rg
-n 6 96 6 12 re f*
+n 6 12 6 12 re f*
.960784 .960784 .862745 rg
-n 12 96 6 12 re f*
+n 12 12 6 12 re f*
.960784 .960784 .862745 rg
-n 24 96 6 12 re f*
+n 24 12 6 12 re f*
.960784 .960784 .862745 rg
-n 30 96 6 12 re f*
+n 30 12 6 12 re f*
.960784 .960784 .862745 rg
-n 36 96 30 12 re f*
+n 36 12 30 12 re f*
.960784 .960784 .862745 rg
-n 72 96 6 12 re f*
+n 72 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 84 12 96 12 re f*
.960784 .960784 .862745 rg
-n 84 96 96 12 re f*
+n 186 12 162 12 re f*
+BT 1 0 0 1 0 38 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (f) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (pass) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# the original function) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (attr1) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("something") Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# setting an attribute) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (attr2) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("something else") Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# setting another attribute) Tj /F3 10 Tf 0 0 0 rg T* T* ET
+Q
+Q
+Q
+Q
+Q
+
+endstream
+endobj
+116 0 obj
+<< /Length 5590 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 667.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
.960784 .960784 .862745 rg
-n 186 96 162 12 re f*
+n -6 -6 468.6898 96 re B*
+Q
+q
.960784 .960784 .862745 rg
n 0 72 6 12 re f*
.960784 .960784 .862745 rg
@@ -7333,37 +7564,37 @@ n 36 12 30 12 re f*
n 72 12 234 12 re f*
.960784 .960784 .862745 rg
n 0 0 96 12 re f*
-BT 1 0 0 1 0 122 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (f) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg ( ) Tj /F5 10 Tf 0 .501961 0 rg (pass) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# the original function) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (attr1) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("something") Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# setting an attribute) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (attr2) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("something else") Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# setting another attribute) Tj /F3 10 Tf 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (traced_f) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (trace) Tj 0 0 0 rg (\() Tj 0 0 0 rg (f) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# the decorated function) Tj /F3 10 Tf 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (traced_f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (attr1) Tj 0 0 0 rg T* .729412 .129412 .129412 rg ('something') Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (traced_f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (attr2) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("something different") Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# setting attr) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (attr2) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# the original attribute did not change) Tj /F3 10 Tf 0 0 0 rg T* .729412 .129412 .129412 rg ('something else') Tj T* ET
+BT 1 0 0 1 0 74 Tm 12 TL /F3 10 Tf .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (traced_f) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (trace) Tj 0 0 0 rg (\() Tj 0 0 0 rg (f) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# the decorated function) Tj /F3 10 Tf 0 0 0 rg T* T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (traced_f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (attr1) Tj 0 0 0 rg T* .729412 .129412 .129412 rg ('something') Tj 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (traced_f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (attr2) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("something different") Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# setting attr) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (>) Tj (>) Tj (>) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (f) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (attr2) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# the original attribute did not change) Tj /F3 10 Tf 0 0 0 rg T* .729412 .129412 .129412 rg ('something else') Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 473.6236 cm
+1 0 0 1 62.69291 634.8236 cm
q
BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (LICENSE) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 455.6236 cm
+1 0 0 1 62.69291 616.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Copyright \(c\) 2005-2015, Michele Simionato All rights reserved.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 425.6236 cm
+1 0 0 1 62.69291 586.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.328555 Tw (Redistribution and use in source and binary forms, with or without modification, are permitted provided) Tj T* 0 Tw (that the following conditions are met:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 419.6236 cm
+1 0 0 1 62.69291 580.8236 cm
Q
q
-1 0 0 1 62.69291 371.6236 cm
+1 0 0 1 62.69291 532.8236 cm
0 0 0 rg
BT /F1 10 Tf 12 TL ET
BT 1 0 0 1 0 2 Tm T* ET
@@ -7378,17 +7609,17 @@ q
Q
Q
q
-1 0 0 1 62.69291 371.6236 cm
+1 0 0 1 62.69291 532.8236 cm
Q
q
-1 0 0 1 62.69291 245.6236 cm
+1 0 0 1 62.69291 406.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 110 Tm /F1 10 Tf 12 TL .17998 Tw (THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND) Tj T* 0 Tw 2.911797 Tw (ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED) Tj T* 0 Tw 5.165529 Tw (WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE) Tj T* 0 Tw 1.395433 Tw (DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE) Tj T* 0 Tw 5.53122 Tw (FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL) Tj T* 0 Tw 2.705976 Tw (DAMAGES \(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR) Tj T* 0 Tw 3.868976 Tw (SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION\) HOWEVER) Tj T* 0 Tw 1.326647 Tw (CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR) Tj T* 0 Tw 1.525366 Tw (TORT \(INCLUDING NEGLIGENCE OR OTHERWISE\) ARISING IN ANY WAY OUT OF THE USE OF) Tj T* 0 Tw (THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 215.6236 cm
+1 0 0 1 62.69291 376.8236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .407132 Tw (If you use this software and you are happy with it, consider sending me a note, just to gratify my ego. On) Tj T* 0 Tw (the other hand, if you use this software and you are unhappy with it, send me a patch!) Tj T* ET
@@ -7397,65 +7628,68 @@ Q
endstream
endobj
-112 0 obj
-<< /Nums [ 0 113 0 R 1 114 0 R 2 115 0 R 3 116 0 R 4 117 0 R
- 5 118 0 R 6 119 0 R 7 120 0 R 8 121 0 R 9 122 0 R
- 10 123 0 R 11 124 0 R 12 125 0 R 13 126 0 R 14 127 0 R
- 15 128 0 R 16 129 0 R ] >>
+117 0 obj
+<< /Nums [ 0 118 0 R 1 119 0 R 2 120 0 R 3 121 0 R 4 122 0 R
+ 5 123 0 R 6 124 0 R 7 125 0 R 8 126 0 R 9 127 0 R
+ 10 128 0 R 11 129 0 R 12 130 0 R 13 131 0 R 14 132 0 R
+ 15 133 0 R 16 134 0 R 17 135 0 R ] >>
endobj
-113 0 obj
+118 0 obj
<< /S /D /St 1 >>
endobj
-114 0 obj
+119 0 obj
<< /S /D /St 2 >>
endobj
-115 0 obj
+120 0 obj
<< /S /D /St 3 >>
endobj
-116 0 obj
+121 0 obj
<< /S /D /St 4 >>
endobj
-117 0 obj
+122 0 obj
<< /S /D /St 5 >>
endobj
-118 0 obj
+123 0 obj
<< /S /D /St 6 >>
endobj
-119 0 obj
+124 0 obj
<< /S /D /St 7 >>
endobj
-120 0 obj
+125 0 obj
<< /S /D /St 8 >>
endobj
-121 0 obj
+126 0 obj
<< /S /D /St 9 >>
endobj
-122 0 obj
+127 0 obj
<< /S /D /St 10 >>
endobj
-123 0 obj
+128 0 obj
<< /S /D /St 11 >>
endobj
-124 0 obj
+129 0 obj
<< /S /D /St 12 >>
endobj
-125 0 obj
+130 0 obj
<< /S /D /St 13 >>
endobj
-126 0 obj
+131 0 obj
<< /S /D /St 14 >>
endobj
-127 0 obj
+132 0 obj
<< /S /D /St 15 >>
endobj
-128 0 obj
+133 0 obj
<< /S /D /St 16 >>
endobj
-129 0 obj
+134 0 obj
<< /S /D /St 17 >>
endobj
+135 0 obj
+<< /S /D /St 18 >>
+endobj
xref
-0 130
+0 136
0000000000 65535 f
0000000075 00000 n
0000000162 00000 n
@@ -7504,93 +7738,99 @@ xref
0000007415 00000 n
0000007587 00000 n
0000007759 00000 n
-0000007878 00000 n
-0000008405 00000 n
-0000008615 00000 n
-0000008820 00000 n
-0000008934 00000 n
-0000009051 00000 n
-0000009278 00000 n
-0000009514 00000 n
-0000009724 00000 n
-0000009920 00000 n
-0000010149 00000 n
-0000010360 00000 n
-0000010571 00000 n
-0000010782 00000 n
-0000010993 00000 n
-0000011204 00000 n
-0000011395 00000 n
-0000011613 00000 n
-0000011850 00000 n
-0000012061 00000 n
-0000012272 00000 n
-0000012483 00000 n
-0000012694 00000 n
-0000012889 00000 n
-0000013119 00000 n
-0000013330 00000 n
-0000013440 00000 n
-0000013688 00000 n
-0000013766 00000 n
-0000013890 00000 n
-0000014018 00000 n
-0000014160 00000 n
-0000014289 00000 n
-0000014431 00000 n
-0000014561 00000 n
-0000014696 00000 n
-0000014834 00000 n
-0000014971 00000 n
-0000015097 00000 n
-0000015231 00000 n
-0000015363 00000 n
-0000015504 00000 n
-0000015645 00000 n
-0000015798 00000 n
-0000015933 00000 n
-0000016074 00000 n
-0000016186 00000 n
-0000016367 00000 n
-0000025100 00000 n
-0000032766 00000 n
-0000047629 00000 n
-0000063771 00000 n
-0000085342 00000 n
-0000106039 00000 n
-0000124340 00000 n
-0000141536 00000 n
-0000154183 00000 n
-0000171186 00000 n
-0000184694 00000 n
-0000200875 00000 n
-0000213965 00000 n
-0000231063 00000 n
-0000238771 00000 n
-0000251385 00000 n
-0000261892 00000 n
-0000262117 00000 n
-0000262155 00000 n
-0000262193 00000 n
-0000262231 00000 n
-0000262269 00000 n
-0000262307 00000 n
-0000262345 00000 n
-0000262383 00000 n
-0000262421 00000 n
-0000262459 00000 n
-0000262498 00000 n
-0000262537 00000 n
-0000262576 00000 n
-0000262615 00000 n
-0000262654 00000 n
-0000262693 00000 n
-0000262732 00000 n
+0000007931 00000 n
+0000008103 00000 n
+0000008644 00000 n
+0000008763 00000 n
+0000008974 00000 n
+0000009179 00000 n
+0000009293 00000 n
+0000009410 00000 n
+0000009637 00000 n
+0000009874 00000 n
+0000010085 00000 n
+0000010296 00000 n
+0000010492 00000 n
+0000010722 00000 n
+0000010933 00000 n
+0000011144 00000 n
+0000011355 00000 n
+0000011566 00000 n
+0000011757 00000 n
+0000011987 00000 n
+0000012205 00000 n
+0000012435 00000 n
+0000012646 00000 n
+0000012857 00000 n
+0000013068 00000 n
+0000013279 00000 n
+0000013474 00000 n
+0000013704 00000 n
+0000013915 00000 n
+0000014025 00000 n
+0000014273 00000 n
+0000014351 00000 n
+0000014468 00000 n
+0000014596 00000 n
+0000014738 00000 n
+0000014867 00000 n
+0000015009 00000 n
+0000015139 00000 n
+0000015274 00000 n
+0000015412 00000 n
+0000015549 00000 n
+0000015675 00000 n
+0000015809 00000 n
+0000015941 00000 n
+0000016082 00000 n
+0000016223 00000 n
+0000016376 00000 n
+0000016511 00000 n
+0000016663 00000 n
+0000016804 00000 n
+0000016916 00000 n
+0000017104 00000 n
+0000024719 00000 n
+0000032191 00000 n
+0000044755 00000 n
+0000061374 00000 n
+0000079955 00000 n
+0000097641 00000 n
+0000118055 00000 n
+0000136810 00000 n
+0000151520 00000 n
+0000165801 00000 n
+0000182131 00000 n
+0000198293 00000 n
+0000212006 00000 n
+0000228125 00000 n
+0000241220 00000 n
+0000248637 00000 n
+0000264749 00000 n
+0000270397 00000 n
+0000270633 00000 n
+0000270671 00000 n
+0000270709 00000 n
+0000270747 00000 n
+0000270785 00000 n
+0000270823 00000 n
+0000270861 00000 n
+0000270899 00000 n
+0000270937 00000 n
+0000270975 00000 n
+0000271014 00000 n
+0000271053 00000 n
+0000271092 00000 n
+0000271131 00000 n
+0000271170 00000 n
+0000271209 00000 n
+0000271248 00000 n
+0000271287 00000 n
trailer
<< /ID
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
- [(\3159\006]o\013h8'\221\251\303\362"\211^) (\3159\006]o\013h8'\221\251\303\362"\211^)]
- /Info 74 0 R /Root 73 0 R /Size 130 >>
+ [(\231\262\373k\004\241\377\267mp#\237\330Gl\026) (\231\262\373k\004\241\377\267mp#\237\330Gl\026)]
+ /Info 77 0 R /Root 76 0 R /Size 136 >>
startxref
-262771
+271326
%%EOF
diff --git a/documentation.rst b/documentation.rst
index 107055b..ac4b152 100644
--- a/documentation.rst
+++ b/documentation.rst
@@ -4,7 +4,7 @@ The ``decorator`` module
:Author: Michele Simionato
:E-mail: michele.simionato@gmail.com
-:Version: 4.0.0 (2015-07-21)
+:Version: 4.0.0 (2015-07-22)
:Supports: Python 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5
:Download page: http://pypi.python.org/pypi/decorator/4.0.0
:Installation: ``pip install decorator``
@@ -12,46 +12,54 @@ The ``decorator`` module
.. contents::
-Compatibility notes
+Introduction
-----------------------------------------
The decorator module is over ten years old, but still alive and
-kicking. It is used by several frameworks and has been stable for a
-*long* time. Even version 4.0 is compatible with the past, except for
-one thing: support for Python 2.4 and 2.5 has been dropped. That
-decision made it possible to use a single code base both for Python
-2.X and Python 3.X. This is a *huge* bonus, since I could remove over
-2,000 lines of duplicated documentation. Having to maintain separate
-docs for Python 2 and Python 3 effectively stopped any development on
-the module for several years. Moreover, it is now trivial to
-distribute the module as a wheel since 2to3 is no more required.
-
-This version supports all Python releases from 2.6 up to 3.5. If
-you need to support ancient versions of Python, stick with the
-decorator module version 3.4.2.
+kicking. It is used by several frameworks (IPython, scipy,
+pyramid,...) and has been stable for a *long* time. It is your best
+option if you want to preserve the signature of decorated functions in
+a consistent way across Python releases. Version 4.0 is fully
+compatible with the past, except for one thing: support for Python 2.4
+and 2.5 has been dropped. That decision made it possible to use a
+single code base both for Python 2.X and Python 3.X. This is a *huge*
+bonus, since I could remove over 2,000 lines of duplicated
+documentation/doctests. Having to maintain separate docs for Python 2 and
+Python 3 effectively stopped any development on the module for several
+years. Moreover, it is now trivial to distribute the module as a wheel
+since 2to3 is no more required. Since Python 2.5 has been released 9
+years ago, I felt that it was reasonable to drop the support for it. If you
+need to support ancient versions of Python, stick with the decorator
+module version 3.4.2. This version supports all Python releases from
+2.6 up to 3.5, which currently is still in beta status.
What's new
---------------------
Since now there is a single manual for all Python versions, I took the
occasion for overhauling the documentation. Therefore, even if you are
-an old time user, you may want to read the manual again, since several
-examples have been improved. A new utility function ``decorate(func,
-caller)` has been added, doing the same job that in the past was done
+an old time user, you may want to read the docs again, since several
+examples have been improved. The packaging has been improved and now
+I am also distributing the code in wheel format. The integration
+with setuptools has been improved and now you can use
+``python setup.py test`` to run the tests.
+A new utility function ``decorate(func,
+caller)`` has been added, doing the same job that in the past was done
by ``decorator(caller, func)``. The old functionality is still there
for compatibility sake, but it is deprecated and not documented
anymore.
-Apart from that, there are no changes. There is a new experimental
-feature, though. The decorator module now include an implementation
-of generic (multiple dispatch) functions. The API is designed to
-mimic the one of `functools.singledispatch` but the implementation
-is much simpler and more general; moreover it preserves the signature of
-the decorated functions. For the moment it is there to exemplify
-the power of the module. In the future it could change and/or be
-enhanced/optimized; on the other hand, it could even become
-deprecated. Such is the fate of experimental features. In any case
-it is only 40 lines of code. Take it as food for thought.
+Apart from that, there is a new experimental feature. The decorator
+module now includes an implementation of generic (multiple dispatch)
+functions. The API is designed to mimic the one of
+`functools.singledispatch` but the implementation is much simpler and
+more general; moreover all the decorators involved preserve the
+signature of the decorated functions. For the moment the facility is
+there mostly to exemplify the power of the module. In the future it
+could change and/or be enhanced/optimized; on the other hand, it could
+even become deprecated. Such is the fate of experimental features. In
+any case it is very short and compact, so you can extract it for
+your own use. Take it as food for thought.
Usefulness of decorators
------------------------------------------------
@@ -195,8 +203,7 @@ argument, you will get an error:
Notice even in Python 3.5 `inspect.getargspec` and
`inspect.getfullargspec` (which are deprecated in that release) will
-give the wrong signature. `inspect.signature` will return the right
-signature on the surface.
+give the wrong signature.
The solution
@@ -694,8 +701,8 @@ source code which is probably not what you want:
<BLANKLINE>
(see bug report 1764286_ for an explanation of what is happening).
-Unfortunately the bug is still there, even in Python 2.7 and 3.4 (it
-will be fixed for Python 3.5, thought). There is however a
+Unfortunately the bug is still there, in all versions of Python except
+Python 3.5, which is not yet released. There is however a
workaround. The decorated function has an attribute ``.__wrapped__``,
pointing to the original function. The easy way to get the source code
is to call ``inspect.getsource`` on the undecorated function:
@@ -834,11 +841,11 @@ Multiple dispatch
There has been talk of implementing multiple dispatch (i.e. generic)
functions in Python for over ten years. Last year for the first time
something was done and now in Python 3.4 we have a decorator
-`functools.singledispatch` which can be used to implement generic
+``functools.singledispatch`` which can be used to implement generic
functions. As the name implies, it has the restriction of being
limited to single dispatch, i.e. it is able to dispatch on the first
argument of the function only. The decorator module provide a
-decorator factory `dispatch_on` which can be used to implement generic
+decorator factory ``dispatch_on`` which can be used to implement generic
functions dispatching on any argument; moreover it can manage
dispatching on more than one argument and, of course, it is
signature-preserving.
@@ -846,7 +853,7 @@ signature-preserving.
Here I will give a very concrete example where it is desiderable to
dispatch on the second argument. Suppose you have an XMLWriter class,
which is instantiated with some configuration parameters and has
-a `.write` method which is able to serialize objects to XML:
+a ``.write`` method which is able to serialize objects to XML:
.. code-block:: python
@@ -859,14 +866,14 @@ a `.write` method which is able to serialize objects to XML:
raise NotImplementedError(type(obj))
-Here you want to dispatch on the second argument since the first, `self`
+Here you want to dispatch on the second argument since the first, ``self``
is already taken. The `dispatch_on` facility allows you to specify
the dispatch argument by simply passing its name as a string (notice
that if you mispell the name you will get an error). The function
decorated with `dispatch_on` is turned into a generic function
and it is the one which is called if there are no more specialized
implementations. Usually such default function should raise a
-`NotImplementedError`, thus forcing people to register some implementation.
+``NotImplementedError``, thus forcing people to register some implementation.
The registration can be done with a decorator:
.. code-block:: python
@@ -908,8 +915,8 @@ Rock-Paper-Scissor example:
I have added an ordinal to the Rock-Paper-Scissor classes to simplify
-the implementation. The idea is to define a generic function `win(a,
-b)` of two arguments corresponding to the moves of the first and
+the implementation. The idea is to define a generic function ``win(a,
+b)`` of two arguments corresponding to the moves of the first and
second player respectively. The moves are instances of the classes
Rock, Paper and Scissors; Paper wins over Rock, Scissor wins over
Paper and Rock wins over Scissor. The function will return +1 for a
@@ -971,6 +978,9 @@ Here is the result:
>>> win(Scissor(), Rock())
-1
+Generics and Abstract Base Classes
+-------------------------------------------------
+
Generic functions implementations in Python are
complicated by the existence of "virtual ancestors", i.e. superclasses
which are not in the class hierarchy.
@@ -978,18 +988,20 @@ Consider for instance this class:
.. code-block:: python
- class WithLength(object):
+ class WithLength(collections.Sized):
def __len__(self):
return 0
-This class defines a `__len__` method and as such is
-considered to be a subclass of the abstract base class `Sized`:
+This class defines a ``__len__`` method and as such is
+considered to be a subclass of the abstract base class ``Sized``:
+
+.. code-block:: python
->>> issubclass(WithLength, collections.Sized)
-True
+ >>> issubclass(WithLength, collections.Sized)
+ True
-However, `collections.Sized` is not an ancestor of `WithLenght`.
+However, ``collections.Sized`` is not an ancestor of ``WithLenght``.
Any implementation of generic functions, even
with single dispatch, must go through some contorsion to take into
account the virtual ancestors.
@@ -1012,16 +1024,52 @@ implemented on all classes with a lenght
return len(obj)
-then `get_length` must be defined on `WithLength` instances:
+then ``get_length`` must be defined on ``WithLength`` instances:
->>> get_length(WithLength())
-0
+.. code-block:: python
+
+ >>> get_length(WithLength())
+ 0
+
+Of course this is a contrived example since you could just use the
+builtin ``len``, but you should get the idea.
The implementation of generic functions in the decorator module is
-marked as experimental because it may
-fail in some corner cases. Also, the implementation does not even
-attempt to use a cache, so it is not as fast as it could be.
-Simplicity was the paramount concern of this implementation.
+marked as experimental because it may change in the future.
+Simplicity was preferred over consistency with the way
+``functools.singledispatch`` works in the standard library.
+For instance, suppose we define ``WithLength`` as a virtual
+subclass of ``collections.Set``:
+
+.. code-block:: python
+
+ >>> _ = collections.Set.register(WithLength) # issubclass(WithLength, Set)
+
+Now, let us define an implementation of ``get_length`` specific to set:
+
+.. code-block:: python
+
+ >>> @get_length.register(collections.Set)
+ ... def get_length_set(obj):
+ ... return 1
+
+The current implementation first check in the MRO and then look
+for abstract bases classes; since ``WithLength`` inherits directly
+from ``collections.Sized`` that implementation is found first:
+
+.. code-block:: python
+
+ >>> get_length(WithLength())
+ 0
+
+Generic functions implemented via ``functools.singledispatch`` use
+a more sophisticated lookup algorithm; in particular they are able
+to discern that a ``Set`` is a ``Sized`` object, so the most
+specialized implementation is the one for ``Set`` and the result should be
+1, not 0.
+
+Finally let me notice that the current implementation does not use any
+cache, whereas the one in ``singledispatch`` has a cache.
Caveats and limitations
-------------------------------------------
@@ -1108,7 +1156,7 @@ the module and releasing new versions.
In the present implementation, decorators generated by ``decorator``
can only be used on user-defined Python functions or methods, not on generic
callable objects, nor on built-in functions, due to limitations of the
-``inspect`` module in the standard library.
+``inspect`` module in the standard library, especially for Python 2.X.
There is a restriction on the names of the arguments: for instance,
if try to call an argument ``_call_`` or ``_func_``
diff --git a/src/decorator.py b/src/decorator.py
index fc41c85..4b3fc09 100644
--- a/src/decorator.py
+++ b/src/decorator.py
@@ -295,15 +295,13 @@ class _ABCManager(object):
keeping the partial ordering.
"""
abcs = self.abcs[i]
- if not abcs:
- abcs.append(a)
- return
for j, abc in enumerate(abcs):
- if issubclass(a, abc):
+ if issubclass(a, abc) and a is not abc:
abcs.insert(j, a)
break
else: # less specialized
- abcs.append(a)
+ if a not in abcs:
+ abcs.append(a)
def get_abcs(self, types):
"""
@@ -313,11 +311,10 @@ class _ABCManager(object):
pass
abclist = [Sentinel for _ in self.indices]
for i, t, abcs in zip(self.indices, types, self.abcs):
- mro = t.__mro__
for new in abcs:
if issubclass(t, new):
old = abclist[i]
- if old is Sentinel or issubclass(new, old) or new in mro:
+ if old is Sentinel or issubclass(new, old):
abclist[i] = new
elif issubclass(old, new):
pass
@@ -345,7 +342,7 @@ def dispatch_on(*dispatch_args):
if not set(dispatch_args) <= argset:
raise NameError('Unknown dispatch arguments %s' % dispatch_str)
- typemap = {(object,) * len(dispatch_args): func}
+ typemap = {}
abcman = _ABCManager(len(dispatch_args))
def register(*types):
@@ -355,15 +352,15 @@ def dispatch_on(*dispatch_args):
(len(dispatch_args), len(types)))
def dec(f):
- typemap[types] = f
n_args = len(getfullargspec(f).args)
if n_args < len(dispatch_args):
raise TypeError(
'%s has not enough arguments (got %d, expected %d)' %
(f, n_args, len(dispatch_args)))
for i, t, abc in zip(abcman.indices, types, abcman.abcs):
- if inspect.isabstract(t):
+ if hasattr(type(t), 'register'): # instance of ABCMeta
abcman.insert(i, t)
+ typemap[types] = f
return f
return dec
@@ -374,13 +371,17 @@ def dispatch_on(*dispatch_args):
return typemap[types](*args, **kw)
except KeyError:
pass
- for types in itertools.product(*(t.__mro__ for t in types)):
- f = typemap.get(types)
- if f is None and abcman.abcs: # look in the ABCs
- print(abcman.get_abcs(types))
- f = typemap.get(abcman.get_abcs(types))
+ for types_ in itertools.product(*(t.__mro__ for t in types)):
+ f = typemap.get(types_)
+ if f is not None:
+ return f(*args, **kw)
+
+ # else look at the ABCs
+ if abcman.abcs:
+ f = typemap.get(abcman.get_abcs(types))
if f is not None:
return f(*args, **kw)
+
# else call the default implementation
return func(*args, **kw)
diff --git a/src/tests/documentation.py b/src/tests/documentation.py
index 21d60de..d552cc6 100644
--- a/src/tests/documentation.py
+++ b/src/tests/documentation.py
@@ -14,46 +14,54 @@ The ``decorator`` module
.. contents::
-Compatibility notes
+Introduction
-----------------------------------------
The decorator module is over ten years old, but still alive and
-kicking. It is used by several frameworks and has been stable for a
-*long* time. Even version 4.0 is compatible with the past, except for
-one thing: support for Python 2.4 and 2.5 has been dropped. That
-decision made it possible to use a single code base both for Python
-2.X and Python 3.X. This is a *huge* bonus, since I could remove over
-2,000 lines of duplicated documentation. Having to maintain separate
-docs for Python 2 and Python 3 effectively stopped any development on
-the module for several years. Moreover, it is now trivial to
-distribute the module as a wheel since 2to3 is no more required.
-
-This version supports all Python releases from 2.6 up to 3.5. If
-you need to support ancient versions of Python, stick with the
-decorator module version 3.4.2.
+kicking. It is used by several frameworks (IPython, scipy,
+pyramid,...) and has been stable for a *long* time. It is your best
+option if you want to preserve the signature of decorated functions in
+a consistent way across Python releases. Version 4.0 is fully
+compatible with the past, except for one thing: support for Python 2.4
+and 2.5 has been dropped. That decision made it possible to use a
+single code base both for Python 2.X and Python 3.X. This is a *huge*
+bonus, since I could remove over 2,000 lines of duplicated
+documentation/doctests. Having to maintain separate docs for Python 2 and
+Python 3 effectively stopped any development on the module for several
+years. Moreover, it is now trivial to distribute the module as a wheel
+since 2to3 is no more required. Since Python 2.5 has been released 9
+years ago, I felt that it was reasonable to drop the support for it. If you
+need to support ancient versions of Python, stick with the decorator
+module version 3.4.2. This version supports all Python releases from
+2.6 up to 3.5, which currently is still in beta status.
What's new
---------------------
Since now there is a single manual for all Python versions, I took the
occasion for overhauling the documentation. Therefore, even if you are
-an old time user, you may want to read the manual again, since several
-examples have been improved. A new utility function ``decorate(func,
-caller)` has been added, doing the same job that in the past was done
+an old time user, you may want to read the docs again, since several
+examples have been improved. The packaging has been improved and now
+I am also distributing the code in wheel format. The integration
+with setuptools has been improved and now you can use
+``python setup.py test`` to run the tests.
+A new utility function ``decorate(func,
+caller)`` has been added, doing the same job that in the past was done
by ``decorator(caller, func)``. The old functionality is still there
for compatibility sake, but it is deprecated and not documented
anymore.
-Apart from that, there are no changes. There is a new experimental
-feature, though. The decorator module now include an implementation
-of generic (multiple dispatch) functions. The API is designed to
-mimic the one of `functools.singledispatch` but the implementation
-is much simpler and more general; moreover it preserves the signature of
-the decorated functions. For the moment it is there to exemplify
-the power of the module. In the future it could change and/or be
-enhanced/optimized; on the other hand, it could even become
-deprecated. Such is the fate of experimental features. In any case
-it is only 40 lines of code. Take it as food for thought.
+Apart from that, there is a new experimental feature. The decorator
+module now includes an implementation of generic (multiple dispatch)
+functions. The API is designed to mimic the one of
+`functools.singledispatch` but the implementation is much simpler and
+more general; moreover all the decorators involved preserve the
+signature of the decorated functions. For the moment the facility is
+there mostly to exemplify the power of the module. In the future it
+could change and/or be enhanced/optimized; on the other hand, it could
+even become deprecated. Such is the fate of experimental features. In
+any case it is very short and compact, so you can extract it for
+your own use. Take it as food for thought.
Usefulness of decorators
------------------------------------------------
@@ -176,8 +184,7 @@ argument, you will get an error:
Notice even in Python 3.5 `inspect.getargspec` and
`inspect.getfullargspec` (which are deprecated in that release) will
-give the wrong signature. `inspect.signature` will return the right
-signature on the surface.
+give the wrong signature.
The solution
@@ -553,8 +560,8 @@ $$example
<BLANKLINE>
(see bug report 1764286_ for an explanation of what is happening).
-Unfortunately the bug is still there, even in Python 2.7 and 3.4 (it
-will be fixed for Python 3.5, thought). There is however a
+Unfortunately the bug is still there, in all versions of Python except
+Python 3.5, which is not yet released. There is however a
workaround. The decorated function has an attribute ``.__wrapped__``,
pointing to the original function. The easy way to get the source code
is to call ``inspect.getsource`` on the undecorated function:
@@ -634,11 +641,11 @@ Multiple dispatch
There has been talk of implementing multiple dispatch (i.e. generic)
functions in Python for over ten years. Last year for the first time
something was done and now in Python 3.4 we have a decorator
-`functools.singledispatch` which can be used to implement generic
+``functools.singledispatch`` which can be used to implement generic
functions. As the name implies, it has the restriction of being
limited to single dispatch, i.e. it is able to dispatch on the first
argument of the function only. The decorator module provide a
-decorator factory `dispatch_on` which can be used to implement generic
+decorator factory ``dispatch_on`` which can be used to implement generic
functions dispatching on any argument; moreover it can manage
dispatching on more than one argument and, of course, it is
signature-preserving.
@@ -646,18 +653,18 @@ signature-preserving.
Here I will give a very concrete example where it is desiderable to
dispatch on the second argument. Suppose you have an XMLWriter class,
which is instantiated with some configuration parameters and has
-a `.write` method which is able to serialize objects to XML:
+a ``.write`` method which is able to serialize objects to XML:
$$XMLWriter
-Here you want to dispatch on the second argument since the first, `self`
+Here you want to dispatch on the second argument since the first, ``self``
is already taken. The `dispatch_on` facility allows you to specify
the dispatch argument by simply passing its name as a string (notice
that if you mispell the name you will get an error). The function
decorated with `dispatch_on` is turned into a generic function
and it is the one which is called if there are no more specialized
implementations. Usually such default function should raise a
-`NotImplementedError`, thus forcing people to register some implementation.
+``NotImplementedError``, thus forcing people to register some implementation.
The registration can be done with a decorator:
$$writefloat
@@ -682,8 +689,8 @@ $$Paper
$$Scissor
I have added an ordinal to the Rock-Paper-Scissor classes to simplify
-the implementation. The idea is to define a generic function `win(a,
-b)` of two arguments corresponding to the moves of the first and
+the implementation. The idea is to define a generic function ``win(a,
+b)`` of two arguments corresponding to the moves of the first and
second player respectively. The moves are instances of the classes
Rock, Paper and Scissors; Paper wins over Rock, Scissor wins over
Paper and Rock wins over Scissor. The function will return +1 for a
@@ -721,6 +728,9 @@ Here is the result:
>>> win(Scissor(), Rock())
-1
+Generics and Abstract Base Classes
+-------------------------------------------------
+
Generic functions implementations in Python are
complicated by the existence of "virtual ancestors", i.e. superclasses
which are not in the class hierarchy.
@@ -728,13 +738,15 @@ Consider for instance this class:
$$WithLength
-This class defines a `__len__` method and as such is
-considered to be a subclass of the abstract base class `Sized`:
+This class defines a ``__len__`` method and as such is
+considered to be a subclass of the abstract base class ``Sized``:
+
+.. code-block:: python
->>> issubclass(WithLength, collections.Sized)
-True
+ >>> issubclass(WithLength, collections.Sized)
+ True
-However, `collections.Sized` is not an ancestor of `WithLenght`.
+However, ``collections.Sized`` is not an ancestor of ``WithLenght``.
Any implementation of generic functions, even
with single dispatch, must go through some contorsion to take into
account the virtual ancestors.
@@ -747,16 +759,52 @@ implemented on all classes with a lenght
$$get_length_sized
-then `get_length` must be defined on `WithLength` instances:
+then ``get_length`` must be defined on ``WithLength`` instances:
->>> get_length(WithLength())
-0
+.. code-block:: python
+
+ >>> get_length(WithLength())
+ 0
+
+Of course this is a contrived example since you could just use the
+builtin ``len``, but you should get the idea.
The implementation of generic functions in the decorator module is
-marked as experimental because it may
-fail in some corner cases. Also, the implementation does not even
-attempt to use a cache, so it is not as fast as it could be.
-Simplicity was the paramount concern of this implementation.
+marked as experimental because it may change in the future.
+Simplicity was preferred over consistency with the way
+``functools.singledispatch`` works in the standard library.
+For instance, suppose we define ``WithLength`` as a virtual
+subclass of ``collections.Set``:
+
+.. code-block:: python
+
+ >>> _ = collections.Set.register(WithLength) # issubclass(WithLength, Set)
+
+Now, let us define an implementation of ``get_length`` specific to set:
+
+.. code-block:: python
+
+ >>> @get_length.register(collections.Set)
+ ... def get_length_set(obj):
+ ... return 1
+
+The current implementation first check in the MRO and then look
+for abstract bases classes; since ``WithLength`` inherits directly
+from ``collections.Sized`` that implementation is found first:
+
+.. code-block:: python
+
+ >>> get_length(WithLength())
+ 0
+
+Generic functions implemented via ``functools.singledispatch`` use
+a more sophisticated lookup algorithm; in particular they are able
+to discern that a ``Set`` is a ``Sized`` object, so the most
+specialized implementation is the one for ``Set`` and the result should be
+1, not 0.
+
+Finally let me notice that the current implementation does not use any
+cache, whereas the one in ``singledispatch`` has a cache.
Caveats and limitations
-------------------------------------------
@@ -843,7 +891,7 @@ the module and releasing new versions.
In the present implementation, decorators generated by ``decorator``
can only be used on user-defined Python functions or methods, not on generic
callable objects, nor on built-in functions, due to limitations of the
-``inspect`` module in the standard library.
+``inspect`` module in the standard library, especially for Python 2.X.
There is a restriction on the names of the arguments: for instance,
if try to call an argument ``_call_`` or ``_func_``
@@ -1326,7 +1374,7 @@ def winPaperScissor(a, b):
return -1
-class WithLength(object):
+class WithLength(collections.Sized):
def __len__(self):
return 0
diff --git a/src/tests/test.py b/src/tests/test.py
index 57f6a06..872d771 100644
--- a/src/tests/test.py
+++ b/src/tests/test.py
@@ -14,7 +14,8 @@ except (SystemError, ValueError):
class DocumentationTestCase(unittest.TestCase):
def test(self):
- doctest.testmod(documentation)
+ err = doctest.testmod(documentation)[0]
+ self.assertEqual(err, 0)
class ExtraTestCase(unittest.TestCase):
@@ -232,11 +233,16 @@ class TestSingleDispatch(unittest.TestCase):
self.assertEqual(g(s), "concrete-set")
self.assertEqual(g(f), "frozen-set")
self.assertEqual(g(t), "tuple")
-
- self.assertEqual(
- [abc.__name__ for abc in g.abcs[0]],
- ['MutableMapping', 'MutableSequence', 'MutableSet', 'Mapping',
- 'Sequence', 'Set', 'Sized'])
+ if hasattr(c, 'ChainMap'):
+ self.assertEqual(
+ [abc.__name__ for abc in g.abcs[0]],
+ ['ChainMap', 'MutableMapping', 'MutableSequence', 'MutableSet',
+ 'Mapping', 'Sequence', 'Set', 'Sized'])
+ else:
+ self.assertEqual(
+ [abc.__name__ for abc in g.abcs[0]],
+ ['MutableMapping', 'MutableSequence', 'MutableSet',
+ 'Mapping', 'Sequence', 'Set', 'Sized'])
def test_mro_conflicts(self):
c = collections
@@ -258,14 +264,13 @@ class TestSingleDispatch(unittest.TestCase):
c.Iterable.register(O)
self.assertEqual(g(o), "sized") # because it's explicitly in __mro__
c.Container.register(O)
- return
self.assertEqual(g(o), "sized") # see above: Sized is in __mro__
c.Set.register(O)
- self.assertEqual(g(o), "set")
- # because c.Set is a subclass of
+ self.assertEqual(g(o), "sized")
+ # could be set because c.Set is a subclass of
# c.Sized and c.Container
- class P:
+ class P(object):
pass
p = P()
self.assertEqual(g(p), "base")
@@ -273,15 +278,9 @@ class TestSingleDispatch(unittest.TestCase):
self.assertEqual(g(p), "iterable")
c.Container.register(P)
- with self.assertRaises(RuntimeError) as re_one:
+ with self.assertRaises(RuntimeError):
g(p)
- self.assertIn(
- str(re_one.exception),
- (("Ambiguous dispatch: <class 'collections.abc.Container'> "
- "or <class 'collections.abc.Iterable'>"),
- ("Ambiguous dispatch: <class 'collections.abc.Iterable'> "
- "or <class 'collections.abc.Container'>")),
- )
+
class Q(c.Sized):
def __len__(self):
return 0
@@ -290,46 +289,50 @@ class TestSingleDispatch(unittest.TestCase):
c.Iterable.register(Q)
self.assertEqual(g(q), "sized") # because it's explicitly in __mro__
c.Set.register(Q)
- self.assertEqual(g(q), "set") # because c.Set is a subclass of
- # c.Sized and c.Iterable
- @functools.singledispatch
- def h(arg):
+ self.assertEqual(g(q), "sized")
+ # could be because c.Set is a subclass of
+ # c.Sized and c.Iterable
+
+ @singledispatch
+ def h(obj):
return "base"
+
@h.register(c.Sized)
- def _(arg):
+ def h_sized(arg):
return "sized"
+
@h.register(c.Container)
- def _(arg):
+ def h_container(arg):
return "container"
# Even though Sized and Container are explicit bases of MutableMapping,
# this ABC is implicitly registered on defaultdict which makes all of
# MutableMapping's bases implicit as well from defaultdict's
# perspective.
- with self.assertRaises(RuntimeError) as re_two:
+ with self.assertRaises(RuntimeError):
h(c.defaultdict(lambda: 0))
- self.assertIn(
- str(re_two.exception),
- (("Ambiguous dispatch: <class 'collections.abc.Container'> "
- "or <class 'collections.abc.Sized'>"),
- ("Ambiguous dispatch: <class 'collections.abc.Sized'> "
- "or <class 'collections.abc.Container'>")),
- )
+
class R(c.defaultdict):
pass
c.MutableSequence.register(R)
- @functools.singledispatch
- def i(arg):
+
+ @singledispatch
+ def i(obj):
return "base"
+
@i.register(c.MutableMapping)
- def _(arg):
+ def i_mapping(arg):
return "mapping"
+
@i.register(c.MutableSequence)
- def _(arg):
+ def i_sequence(arg):
return "sequence"
r = R()
- self.assertEqual(i(r), "sequence")
+ with self.assertRaises(RuntimeError): # not for standardlib
+ self.assertEqual(i(r), "sequence")
+
class S:
pass
+
class T(S, c.Sized):
def __len__(self):
return 0
@@ -337,40 +340,42 @@ class TestSingleDispatch(unittest.TestCase):
self.assertEqual(h(t), "sized")
c.Container.register(T)
self.assertEqual(h(t), "sized") # because it's explicitly in the MRO
+
class U:
def __len__(self):
return 0
u = U()
- self.assertEqual(h(u), "sized") # implicit Sized subclass inferred
- # from the existence of __len__()
+ if sys.version >= '3':
+ self.assertEqual(h(u), "sized")
+ # implicit Sized subclass inferred
+ # from the existence of __len__()
+
c.Container.register(U)
# There is no preference for registered versus inferred ABCs.
- with self.assertRaises(RuntimeError) as re_three:
+ with self.assertRaises(RuntimeError):
h(u)
- self.assertIn(
- str(re_three.exception),
- (("Ambiguous dispatch: <class 'collections.abc.Container'> "
- "or <class 'collections.abc.Sized'>"),
- ("Ambiguous dispatch: <class 'collections.abc.Sized'> "
- "or <class 'collections.abc.Container'>")),
- )
+
class V(c.Sized, S):
def __len__(self):
return 0
- @functools.singledispatch
- def j(arg):
+
+ @singledispatch
+ def j(obj):
return "base"
+
@j.register(S)
- def _(arg):
+ def j_s(arg):
return "s"
+
@j.register(c.Container)
- def _(arg):
+ def j_container(arg):
return "container"
v = V()
self.assertEqual(j(v), "s")
c.Container.register(V)
- self.assertEqual(j(v), "container") # because it ends up right after
- # Sized in the MRO
+ self.assertEqual(j(v), "s") # could be "container"
+ # because it ends up right after
+ # Sized in the MRO
if __name__ == '__main__':
unittest.main()