summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Simionato <michele.simionato@gmail.com>2015-07-23 16:33:46 +0200
committerMichele Simionato <michele.simionato@gmail.com>2015-07-23 16:33:46 +0200
commit8b7b3aba63d278eb391c3c9b0ccbe065559f1b93 (patch)
tree5438712066b25f00151e80a0f4741a53d2516193
parentbf1748df8d229bbfe40de6944c48349228e5b5bc (diff)
downloadpython-decorator-git-8b7b3aba63d278eb391c3c9b0ccbe065559f1b93.tar.gz
Improved tests and docs
-rw-r--r--documentation.pdf756
-rw-r--r--documentation.rst98
-rw-r--r--src/tests/documentation.py111
-rw-r--r--src/tests/test.py69
4 files changed, 658 insertions, 376 deletions
diff --git a/documentation.pdf b/documentation.pdf
index dd1b347..8fde909 100644
--- a/documentation.pdf
+++ b/documentation.pdf
@@ -97,16 +97,16 @@ endobj
<< /Border [ 0 0 0 ] /Contents () /Dest [ 64 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 [ 65 0 R /XYZ 62.69291 669.0236 0 ] /Rect [ 62.69291 344.0236 80.47291 356.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 65 0 R /XYZ 62.69291 657.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 [ 65 0 R /XYZ 62.69291 669.0236 0 ] /Rect [ 83.25291 344.0236 161.2529 356.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 65 0 R /XYZ 62.69291 657.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 [ 65 0 R /XYZ 62.69291 669.0236 0 ] /Rect [ 167.2529 344.0236 192.2729 356.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 65 0 R /XYZ 62.69291 657.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 [ 65 0 R /XYZ 62.69291 669.0236 0 ] /Rect [ 521.4627 344.7736 532.5827 356.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 65 0 R /XYZ 62.69291 657.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 [ 67 0 R /XYZ 62.69291 647.8236 0 ] /Rect [ 62.69291 326.0236 177.1629 338.0236 ] /Subtype /Link /Type /Annot >>
@@ -133,23 +133,23 @@ endobj
<< /Border [ 0 0 0 ] /Contents () /Dest [ 72 0 R /XYZ 62.69291 503.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 [ 74 0 R /XYZ 62.69291 491.8236 0 ] /Rect [ 62.69291 254.0236 174.3929 266.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 729.0236 0 ] /Rect [ 62.69291 254.0236 174.3929 266.0236 ] /Subtype /Link /Type /Annot >>
endobj
46 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 74 0 R /XYZ 62.69291 491.8236 0 ] /Rect [ 521.4627 254.7736 532.5827 266.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 729.0236 0 ] /Rect [ 521.4627 254.7736 532.5827 266.7736 ] /Subtype /Link /Type /Annot >>
endobj
47 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 77 0 R /XYZ 62.69291 607.8236 0 ] /Rect [ 62.69291 236.0236 106.0329 248.0236 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 77 0 R /XYZ 62.69291 180.6236 0 ] /Rect [ 62.69291 236.0236 106.0329 248.0236 ] /Subtype /Link /Type /Annot >>
endobj
48 0 obj
-<< /Border [ 0 0 0 ] /Contents () /Dest [ 77 0 R /XYZ 62.69291 607.8236 0 ] /Rect [ 521.4627 236.7736 532.5827 248.7736 ] /Subtype /Link /Type /Annot >>
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 77 0 R /XYZ 62.69291 180.6236 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 47 0 R 48 0 R ] /Contents 101 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 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 102 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
/Trans << >> /Type /Page >>
endobj
50 0 obj
@@ -159,7 +159,7 @@ endobj
<< /A << /S /URI /Type /Action /URI (http://pythonwheels.com/) >> /Border [ 0 0 0 ] /Rect [ 62.69291 630.0236 89.4624 642.0236 ] /Subtype /Link /Type /Annot >>
endobj
52 0 obj
-<< /Annots [ 51 0 R ] /Contents 102 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+<< /Annots [ 51 0 R ] /Contents 103 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
/Trans << >> /Type /Page >>
endobj
53 0 obj
@@ -175,157 +175,161 @@ endobj
<< /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
57 0 obj
-<< /Annots [ 53 0 R 56 0 R ] /Contents 103 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+<< /Annots [ 53 0 R 56 0 R ] /Contents 104 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
/Trans << >> /Type /Page >>
endobj
58 0 obj
-<< /Contents 104 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 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 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
59 0 obj
-<< /Contents 105 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 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 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
60 0 obj
<< /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
61 0 obj
-<< /Annots [ 60 0 R ] /Contents 106 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+<< /Annots [ 60 0 R ] /Contents 107 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
/Trans << >> /Type /Page >>
endobj
62 0 obj
-<< /Contents 107 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 108 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
63 0 obj
-<< /Contents 108 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 109 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
64 0 obj
-<< /Contents 109 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 110 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
65 0 obj
-<< /Contents 110 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 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 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
66 0 obj
<< /A << /S /URI /Type /Action /URI (http://bugs.python.org/issue1764286) >> /Border [ 0 0 0 ] /Rect [ 133.3162 345.2236 172.2473 357.2236 ] /Subtype /Link /Type /Annot >>
endobj
67 0 obj
-<< /Annots [ 66 0 R ] /Contents 111 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+<< /Annots [ 66 0 R ] /Contents 112 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
/Trans << >> /Type /Page >>
endobj
68 0 obj
<< /A << /S /URI /Type /Action /URI (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496691) >> /Border [ 0 0 0 ] /Rect [ 62.69291 515.8236 363.4029 527.8236 ] /Subtype /Link /Type /Annot >>
endobj
69 0 obj
-<< /Annots [ 68 0 R ] /Contents 112 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+<< /Annots [ 68 0 R ] /Contents 113 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
/Trans << >> /Type /Page >>
endobj
70 0 obj
-<< /Contents 113 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 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 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
71 0 obj
-<< /Contents 114 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 115 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
72 0 obj
-<< /Contents 115 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 116 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
73 0 obj
-<< /Contents 116 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 117 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
74 0 obj
-<< /Contents 117 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+<< /Contents 118 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
/Type /Page >>
endobj
75 0 obj
-<< /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 >>
+<< /Contents 119 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
endobj
76 0 obj
-<< /Annots [ 75 0 R ] /Contents 118 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 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-0362) >> /Border [ 0 0 0 ] /Rect [ 301.1597 663.0236 317.8397 675.0236 ] /Subtype /Link /Type /Annot >>
endobj
77 0 obj
-<< /Contents 119 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 100 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
- /Type /Page >>
+<< /Annots [ 76 0 R ] /Contents 120 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
endobj
78 0 obj
-<< /Outlines 80 0 R /PageLabels 120 0 R /PageMode /UseNone /Pages 100 0 R /Type /Catalog >>
+<< /Contents 121 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 101 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
endobj
79 0 obj
-<< /Author (Michele Simionato) /CreationDate (D:20150723140941-01'00') /Creator (\(unspecified\)) /Keywords () /Producer (ReportLab PDF Library - www.reportlab.com) /Subject (\(unspecified\))
- /Title (The decorator module) >>
+<< /Outlines 81 0 R /PageLabels 122 0 R /PageMode /UseNone /Pages 101 0 R /Type /Catalog >>
endobj
80 0 obj
-<< /Count 19 /First 81 0 R /Last 99 0 R /Type /Outlines >>
+<< /Author (Michele Simionato) /CreationDate (D:20150723163253-01'00') /Creator (\(unspecified\)) /Keywords () /Producer (ReportLab PDF Library - www.reportlab.com) /Subject (\(unspecified\))
+ /Title (The decorator module) >>
endobj
81 0 obj
-<< /Dest [ 52 0 R /XYZ 62.69291 765.0236 0 ] /Next 82 0 R /Parent 80 0 R /Title (Introduction) >>
+<< /Count 19 /First 82 0 R /Last 100 0 R /Type /Outlines >>
endobj
82 0 obj
-<< /Dest [ 52 0 R /XYZ 62.69291 582.0236 0 ] /Next 83 0 R /Parent 80 0 R /Prev 81 0 R /Title (What's new) >>
+<< /Dest [ 52 0 R /XYZ 62.69291 765.0236 0 ] /Next 83 0 R /Parent 81 0 R /Title (Introduction) >>
endobj
83 0 obj
-<< /Dest [ 52 0 R /XYZ 62.69291 369.0236 0 ] /Next 84 0 R /Parent 80 0 R /Prev 82 0 R /Title (Usefulness of decorators) >>
+<< /Dest [ 52 0 R /XYZ 62.69291 582.0236 0 ] /Next 84 0 R /Parent 81 0 R /Prev 82 0 R /Title (What's new) >>
endobj
84 0 obj
-<< /Dest [ 57 0 R /XYZ 62.69291 765.0236 0 ] /Next 85 0 R /Parent 80 0 R /Prev 83 0 R /Title (Definitions) >>
+<< /Dest [ 52 0 R /XYZ 62.69291 369.0236 0 ] /Next 85 0 R /Parent 81 0 R /Prev 83 0 R /Title (Usefulness of decorators) >>
endobj
85 0 obj
-<< /Dest [ 57 0 R /XYZ 62.69291 528.0236 0 ] /Next 86 0 R /Parent 80 0 R /Prev 84 0 R /Title (Statement of the problem) >>
+<< /Dest [ 57 0 R /XYZ 62.69291 765.0236 0 ] /Next 86 0 R /Parent 81 0 R /Prev 84 0 R /Title (Definitions) >>
endobj
86 0 obj
-<< /Dest [ 58 0 R /XYZ 62.69291 469.4236 0 ] /Next 87 0 R /Parent 80 0 R /Prev 85 0 R /Title (The solution) >>
+<< /Dest [ 57 0 R /XYZ 62.69291 528.0236 0 ] /Next 87 0 R /Parent 81 0 R /Prev 85 0 R /Title (Statement of the problem) >>
endobj
87 0 obj
-<< /Dest [ 59 0 R /XYZ 62.69291 492.6236 0 ] /Next 88 0 R /Parent 80 0 R /Prev 86 0 R /Title (A trace decorator) >>
+<< /Dest [ 58 0 R /XYZ 62.69291 469.4236 0 ] /Next 88 0 R /Parent 81 0 R /Prev 86 0 R /Title (The solution) >>
endobj
88 0 obj
-<< /Dest [ 61 0 R /XYZ 62.69291 631.8236 0 ] /Next 89 0 R /Parent 80 0 R /Prev 87 0 R /Title (Function annotations) >>
+<< /Dest [ 59 0 R /XYZ 62.69291 492.6236 0 ] /Next 89 0 R /Parent 81 0 R /Prev 87 0 R /Title (A trace decorator) >>
endobj
89 0 obj
-<< /Dest [ 62 0 R /XYZ 62.69291 765.0236 0 ] /Next 90 0 R /Parent 80 0 R /Prev 88 0 R /Title (decorator.decorator) >>
+<< /Dest [ 61 0 R /XYZ 62.69291 631.8236 0 ] /Next 90 0 R /Parent 81 0 R /Prev 88 0 R /Title (Function annotations) >>
endobj
90 0 obj
-<< /Dest [ 62 0 R /XYZ 62.69291 317.2236 0 ] /Next 91 0 R /Parent 80 0 R /Prev 89 0 R /Title (blocking) >>
+<< /Dest [ 62 0 R /XYZ 62.69291 765.0236 0 ] /Next 91 0 R /Parent 81 0 R /Prev 89 0 R /Title (decorator.decorator) >>
endobj
91 0 obj
-<< /Dest [ 63 0 R /XYZ 62.69291 434.6236 0 ] /Next 92 0 R /Parent 80 0 R /Prev 90 0 R /Title (decorator\(cls\)) >>
+<< /Dest [ 62 0 R /XYZ 62.69291 317.2236 0 ] /Next 92 0 R /Parent 81 0 R /Prev 90 0 R /Title (blocking) >>
endobj
92 0 obj
-<< /Dest [ 64 0 R /XYZ 62.69291 542.6236 0 ] /Next 93 0 R /Parent 80 0 R /Prev 91 0 R /Title (contextmanager) >>
+<< /Dest [ 63 0 R /XYZ 62.69291 434.6236 0 ] /Next 93 0 R /Parent 81 0 R /Prev 91 0 R /Title (decorator\(cls\)) >>
endobj
93 0 obj
-<< /Dest [ 65 0 R /XYZ 62.69291 669.0236 0 ] /Next 94 0 R /Parent 80 0 R /Prev 92 0 R /Title (The FunctionMaker class) >>
+<< /Dest [ 64 0 R /XYZ 62.69291 542.6236 0 ] /Next 94 0 R /Parent 81 0 R /Prev 92 0 R /Title (contextmanager) >>
endobj
94 0 obj
-<< /Dest [ 67 0 R /XYZ 62.69291 647.8236 0 ] /Next 95 0 R /Parent 80 0 R /Prev 93 0 R /Title (Getting the source code) >>
+<< /Dest [ 65 0 R /XYZ 62.69291 657.0236 0 ] /Next 95 0 R /Parent 81 0 R /Prev 93 0 R /Title (The FunctionMaker class) >>
endobj
95 0 obj
-<< /Dest [ 67 0 R /XYZ 62.69291 180.0236 0 ] /Next 96 0 R /Parent 80 0 R /Prev 94 0 R /Title (Dealing with third party decorators) >>
+<< /Dest [ 67 0 R /XYZ 62.69291 647.8236 0 ] /Next 96 0 R /Parent 81 0 R /Prev 94 0 R /Title (Getting the source code) >>
endobj
96 0 obj
-<< /Dest [ 70 0 R /XYZ 62.69291 445.4236 0 ] /Next 97 0 R /Parent 80 0 R /Prev 95 0 R /Title (Multiple dispatch) >>
+<< /Dest [ 67 0 R /XYZ 62.69291 180.0236 0 ] /Next 97 0 R /Parent 81 0 R /Prev 95 0 R /Title (Dealing with third party decorators) >>
endobj
97 0 obj
-<< /Dest [ 72 0 R /XYZ 62.69291 503.8236 0 ] /Next 98 0 R /Parent 80 0 R /Prev 96 0 R /Title (Generic functions and virtual ancestors) >>
+<< /Dest [ 70 0 R /XYZ 62.69291 445.4236 0 ] /Next 98 0 R /Parent 81 0 R /Prev 96 0 R /Title (Multiple dispatch) >>
endobj
98 0 obj
-<< /Dest [ 74 0 R /XYZ 62.69291 491.8236 0 ] /Next 99 0 R /Parent 80 0 R /Prev 97 0 R /Title (Caveats and limitations) >>
+<< /Dest [ 72 0 R /XYZ 62.69291 503.8236 0 ] /Next 99 0 R /Parent 81 0 R /Prev 97 0 R /Title (Generic functions and virtual ancestors) >>
endobj
99 0 obj
-<< /Dest [ 77 0 R /XYZ 62.69291 607.8236 0 ] /Parent 80 0 R /Prev 98 0 R /Title (LICENSE) >>
+<< /Dest [ 75 0 R /XYZ 62.69291 729.0236 0 ] /Next 100 0 R /Parent 81 0 R /Prev 98 0 R /Title (Caveats and limitations) >>
endobj
100 0 obj
-<< /Count 19 /Kids [ 49 0 R 52 0 R 57 0 R 58 0 R 59 0 R 61 0 R 62 0 R 63 0 R 64 0 R 65 0 R
- 67 0 R 69 0 R 70 0 R 71 0 R 72 0 R 73 0 R 74 0 R 76 0 R 77 0 R ] /Type /Pages >>
+<< /Dest [ 77 0 R /XYZ 62.69291 180.6236 0 ] /Parent 81 0 R /Prev 99 0 R /Title (LICENSE) >>
endobj
101 0 obj
+<< /Count 20 /Kids [ 49 0 R 52 0 R 57 0 R 58 0 R 59 0 R 61 0 R 62 0 R 63 0 R 64 0 R 65 0 R
+ 67 0 R 69 0 R 70 0 R 71 0 R 72 0 R 73 0 R 74 0 R 75 0 R 77 0 R 78 0 R ] /Type /Pages >>
+endobj
+102 0 obj
<< /Length 7563 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -740,7 +744,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 (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
@@ -763,7 +767,7 @@ Q
endstream
endobj
-102 0 obj
+103 0 obj
<< /Length 7477 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -934,7 +938,7 @@ Q
endstream
endobj
-103 0 obj
+104 0 obj
<< /Length 12505 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -1265,7 +1269,7 @@ Q
endstream
endobj
-104 0 obj
+105 0 obj
<< /Length 16560 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -1745,7 +1749,7 @@ Q
endstream
endobj
-105 0 obj
+106 0 obj
<< /Length 18522 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -2338,7 +2342,7 @@ Q
endstream
endobj
-106 0 obj
+107 0 obj
<< /Length 17634 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -2849,7 +2853,7 @@ Q
endstream
endobj
-107 0 obj
+108 0 obj
<< /Length 20355 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -3415,7 +3419,7 @@ Q
endstream
endobj
-108 0 obj
+109 0 obj
<< /Length 18696 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -3918,8 +3922,8 @@ Q
endstream
endobj
-109 0 obj
-<< /Length 14651 >>
+110 0 obj
+<< /Length 14654 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -4335,42 +4339,42 @@ Q
q
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
+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 2.323984 Tw (example will break in older versions of Python \(you can solve this by installing ) Tj /F3 10 Tf 0 0 0 rg (contextlib2) Tj /F1 10 Tf 0 0 0 rg (\); the) Tj T* 0 Tw ET
Q
Q
endstream
endobj
-110 0 obj
-<< /Length 14222 >>
+111 0 obj
+<< /Length 14329 >>
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 669.0236 cm
q
-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
+BT 1 0 0 1 0 86 Tm 1.819147 Tw 12 TL /F1 10 Tf 0 0 0 rg (second is that ) Tj /F3 10 Tf 0 0 0 rg (GeneratorContextManager ) Tj /F1 10 Tf 0 0 0 rg (objects do not preserve the signature of the decorated) Tj T* 0 Tw 13.76298 Tw (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 generic signature) Tj T* 0 Tw 2.777674 Tw /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 arguments. For such) Tj T* 0 Tw 3.697976 Tw (reasons the decorator module, starting with release 3.4, offers a ) Tj /F3 10 Tf 0 0 0 rg (decorator.contextmanager) Tj T* 0 Tw .70936 Tw /F1 10 Tf 0 0 0 rg (decorator that solves both problems and works in all supported Python versions. The usage is the same) Tj T* 0 Tw 11.01622 Tw (and factories decorated with ) Tj /F3 10 Tf 0 0 0 rg (decorator.contextmanager ) Tj /F1 10 Tf 0 0 0 rg (will returns instances of) Tj T* 0 Tw 4.152823 Tw /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 a ) Tj /F3 10 Tf 0 0 0 rg (__call__) Tj T* 0 Tw /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 648.0236 cm
+1 0 0 1 62.69291 636.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 582.0236 cm
+1 0 0 1 62.69291 570.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 540.0236 cm
+1 0 0 1 62.69291 528.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 446.8236 cm
+1 0 0 1 62.69291 434.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -4498,25 +4502,25 @@ Q
Q
Q
q
-1 0 0 1 62.69291 414.8236 cm
+1 0 0 1 62.69291 402.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 372.8236 cm
+1 0 0 1 62.69291 360.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 330.8236 cm
+1 0 0 1 62.69291 318.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 237.6236 cm
+1 0 0 1 62.69291 225.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -4634,7 +4638,7 @@ Q
Q
Q
q
-1 0 0 1 62.69291 97.62362 cm
+1 0 0 1 62.69291 85.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
@@ -4642,7 +4646,7 @@ Q
endstream
endobj
-111 0 obj
+112 0 obj
<< /Length 18456 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -5159,7 +5163,7 @@ Q
endstream
endobj
-112 0 obj
+113 0 obj
<< /Length 16552 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -5577,8 +5581,8 @@ Q
endstream
endobj
-113 0 obj
-<< /Length 12347 >>
+114 0 obj
+<< /Length 12356 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -5792,7 +5796,7 @@ Q
q
1 0 0 1 62.69291 334.4236 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 .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
+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 1.46332 Tw (Last year for the first time something concrete 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
@@ -5902,7 +5906,7 @@ Q
endstream
endobj
-114 0 obj
+115 0 obj
<< /Length 16993 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -6451,7 +6455,7 @@ Q
endstream
endobj
-115 0 obj
+116 0 obj
<< /Length 14183 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
@@ -6908,8 +6912,8 @@ Q
endstream
endobj
-116 0 obj
-<< /Length 13101 >>
+117 0 obj
+<< /Length 13146 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
@@ -6957,7 +6961,7 @@ Q
q
1 0 0 1 62.69291 653.8236 cm
q
-BT 1 0 0 1 0 26 Tm .129461 Tw 12 TL /F1 10 Tf 0 0 0 rg (Since in Python it is possible to consider any instance of ABCMeta as a virtual ancestor of any other class) Tj T* 0 Tw .21152 Tw (\(it is enough to register it as ) Tj /F3 10 Tf 0 0 0 rg (ancestor.register\(cls\)) Tj /F1 10 Tf 0 0 0 rg (\), any implementation of generic functions must) Tj T* 0 Tw (take this feature into account. Let me give an example.) Tj T* ET
+BT 1 0 0 1 0 26 Tm .129461 Tw 12 TL /F1 10 Tf 0 0 0 rg (Since in Python it is possible to consider any instance of ABCMeta as a virtual ancestor of any other class) Tj T* 0 Tw .21152 Tw (\(it is enough to register it as ) Tj /F3 10 Tf 0 0 0 rg (ancestor.register\(cls\)) Tj /F1 10 Tf 0 0 0 rg (\), any implementation of generic functions must) Tj T* 0 Tw (take virtual ancestors into account. Let me give an example.) Tj T* ET
Q
Q
q
@@ -7013,9 +7017,7 @@ 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*
-.960784 .960784 .862745 rg
-n 108 0 264 12 re f*
-BT 1 0 0 1 0 50 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 (SomeSet) 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 /F6 10 Tf .25098 .501961 .501961 rg (# methods that make SomeSet set-like) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# not shown ...) 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 (__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 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# in reality one would return more than zero) Tj T* ET
+BT 1 0 0 1 0 50 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 (SomeSet) 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 /F6 10 Tf .25098 .501961 .501961 rg (# methods that make SomeSet set-like) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# not shown ...) 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 (__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
@@ -7158,7 +7160,7 @@ Q
q
1 0 0 1 62.69291 326.2236 cm
q
-BT 1 0 0 1 0 14 Tm .210697 Tw 12 TL /F1 10 Tf 0 0 0 rg (The current implementation, as the one used by ) Tj /F3 10 Tf 0 0 0 rg (functools.singledispatch) Tj /F1 10 Tf 0 0 0 rg (, is able to discern that a) Tj T* 0 Tw /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 implementation for ) Tj /F3 10 Tf 0 0 0 rg (Set ) Tj /F1 10 Tf 0 0 0 rg (is taken:) Tj T* ET
+BT 1 0 0 1 0 14 Tm .210697 Tw 12 TL /F1 10 Tf 0 0 0 rg (The current implementation, as the one used by ) Tj /F3 10 Tf 0 0 0 rg (functools.singledispatch) Tj /F1 10 Tf 0 0 0 rg (, is able to discern that a) Tj T* 0 Tw /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 more specific implementation for ) Tj /F3 10 Tf 0 0 0 rg (Set ) Tj /F1 10 Tf 0 0 0 rg (is taken:) Tj T* ET
Q
Q
q
@@ -7190,8 +7192,10 @@ n 90 12 42 12 re f*
.960784 .960784 .862745 rg
n 132 12 18 12 re f*
.960784 .960784 .862745 rg
+n 162 12 282 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 (SomeSet) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg T* .4 .4 .4 rg (1) Tj T* ET
+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 (SomeSet) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# NB: the implementation for Sized would give 0) Tj /F3 10 Tf 0 0 0 rg T* .4 .4 .4 rg (1) Tj T* ET
Q
Q
Q
@@ -7200,7 +7204,7 @@ Q
q
1 0 0 1 62.69291 213.0236 cm
q
-BT 1 0 0 1 0 50 Tm 3.134104 Tw 12 TL /F1 10 Tf 0 0 0 rg (Some times it is not clear how to dispatch. For instance, consider a class ) Tj /F3 10 Tf 0 0 0 rg (C ) Tj /F1 10 Tf 0 0 0 rg (registered both as) Tj T* 0 Tw 6.519974 Tw /F3 10 Tf 0 0 0 rg (collections.Iterable ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized ) Tj /F1 10 Tf 0 0 0 rg (and define a generic function ) Tj /F3 10 Tf 0 0 0 rg (g ) Tj /F1 10 Tf 0 0 0 rg (with) Tj T* 0 Tw 3.101085 Tw (implementations both for ) Tj /F3 10 Tf 0 0 0 rg (collections.Iterable ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized) Tj /F1 10 Tf 0 0 0 rg (. It is impossible to) Tj T* 0 Tw .496651 Tw (decide which implementation to use, since the ancestors are independent, and the following code will fail) Tj T* 0 Tw (with a RuntimeError:) Tj T* ET
+BT 1 0 0 1 0 50 Tm 3.503735 Tw 12 TL /F1 10 Tf 0 0 0 rg (Sometimes it is not clear how to dispatch. For instance, consider a class ) Tj /F3 10 Tf 0 0 0 rg (C ) Tj /F1 10 Tf 0 0 0 rg (registered both as) Tj T* 0 Tw 6.519974 Tw /F3 10 Tf 0 0 0 rg (collections.Iterable ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized ) Tj /F1 10 Tf 0 0 0 rg (and define a generic function ) Tj /F3 10 Tf 0 0 0 rg (g ) Tj /F1 10 Tf 0 0 0 rg (with) Tj T* 0 Tw 3.101085 Tw (implementations both for ) Tj /F3 10 Tf 0 0 0 rg (collections.Iterable ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (collections.Sized) Tj /F1 10 Tf 0 0 0 rg (. It is impossible to) Tj T* 0 Tw .690697 Tw (decide which implementation to use, since the ancestors are independent, and the following function will) Tj T* 0 Tw (raise a RuntimeError when called:) Tj T* ET
Q
Q
q
@@ -7220,9 +7224,9 @@ q
.960784 .960784 .862745 rg
n 0 96 18 12 re f*
.960784 .960784 .862745 rg
-n 24 96 132 12 re f*
+n 24 96 138 12 re f*
.960784 .960784 .862745 rg
-n 156 96 18 12 re f*
+n 162 96 18 12 re f*
.960784 .960784 .862745 rg
n 24 84 84 12 re f*
.960784 .960784 .862745 rg
@@ -7283,7 +7287,7 @@ n 90 0 6 12 re f*
n 96 0 36 12 re f*
.960784 .960784 .862745 rg
n 132 0 12 12 re f*
-BT 1 0 0 1 0 98 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (singledispatch_example) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (singledispatch) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (dispatch_on) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('obj') Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@singledispatch) 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 (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (obj) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (raise) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf .823529 .254902 .227451 rg (NotImplementedError) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (type) Tj 0 0 0 rg (\() Tj 0 0 0 rg (g) Tj 0 0 0 rg (\)\)) Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@g.register) 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* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g_sized) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ET
+BT 1 0 0 1 0 98 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (singledispatch_example1) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (singledispatch) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (dispatch_on) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('obj') Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@singledispatch) 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 (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (obj) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (raise) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf .823529 .254902 .227451 rg (NotImplementedError) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 .501961 0 rg (type) Tj 0 0 0 rg (\() Tj 0 0 0 rg (g) Tj 0 0 0 rg (\)\)) Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@g.register) 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* ( ) Tj /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (g_sized) Tj 0 0 0 rg (\() Tj 0 .501961 0 rg (object) Tj 0 0 0 rg (\):) Tj 0 0 0 rg T* ET
Q
Q
Q
@@ -7292,12 +7296,12 @@ Q
endstream
endobj
-117 0 obj
-<< /Length 6203 >>
+118 0 obj
+<< /Length 12649 >>
stream
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 655.8236 cm
+1 0 0 1 62.69291 667.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -7307,98 +7311,308 @@ q
.662745 .662745 .662745 RG
.5 w
.960784 .960784 .862745 rg
-n -6 -6 468.6898 108 re B*
+n -6 -6 468.6898 96 re B*
Q
q
.960784 .960784 .862745 rg
-n 48 84 36 12 re f*
-.960784 .960784 .862745 rg
-n 90 84 42 12 re f*
-.960784 .960784 .862745 rg
-n 24 60 66 12 re f*
-.960784 .960784 .862745 rg
-n 90 60 6 12 re f*
-.960784 .960784 .862745 rg
-n 96 60 66 12 re f*
-.960784 .960784 .862745 rg
-n 162 60 6 12 re f*
+n 48 72 36 12 re f*
.960784 .960784 .862745 rg
-n 168 60 48 12 re f*
+n 90 72 42 12 re f*
.960784 .960784 .862745 rg
-n 216 60 6 12 re f*
+n 24 48 66 12 re f*
.960784 .960784 .862745 rg
-n 24 48 18 12 re f*
+n 90 48 6 12 re f*
.960784 .960784 .862745 rg
-n 48 48 60 12 re f*
+n 96 48 66 12 re f*
.960784 .960784 .862745 rg
-n 108 48 6 12 re f*
+n 162 48 6 12 re f*
.960784 .960784 .862745 rg
-n 114 48 36 12 re f*
+n 168 48 48 12 re f*
.960784 .960784 .862745 rg
-n 150 48 12 12 re f*
+n 216 48 6 12 re f*
.960784 .960784 .862745 rg
-n 48 36 36 12 re f*
+n 24 36 18 12 re f*
.960784 .960784 .862745 rg
-n 90 36 60 12 re f*
+n 48 36 60 12 re f*
.960784 .960784 .862745 rg
-n 24 12 24 12 re f*
+n 108 36 6 12 re f*
.960784 .960784 .862745 rg
-n 54 12 72 12 re f*
+n 114 36 36 12 re f*
.960784 .960784 .862745 rg
-n 126 12 6 12 re f*
+n 150 36 12 12 re f*
.960784 .960784 .862745 rg
-n 132 12 72 12 re f*
+n 48 24 36 12 re f*
.960784 .960784 .862745 rg
-n 204 12 12 12 re f*
+n 90 24 60 12 re f*
.960784 .960784 .862745 rg
-n 48 0 6 12 re f*
+n 24 0 6 12 re f*
.960784 .960784 .862745 rg
-n 54 0 6 12 re f*
+n 30 0 6 12 re f*
.960784 .960784 .862745 rg
-n 60 0 6 12 re f*
+n 36 0 6 12 re f*
.960784 .960784 .862745 rg
-n 66 0 18 12 re f*
+n 42 0 18 12 re f*
.960784 .960784 .862745 rg
-n 96 0 240 12 re f*
-BT 1 0 0 1 0 86 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 .729412 .129412 .129412 rg ("sized") Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@g.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (collections) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Iterable) 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 (g_iterable) Tj 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 (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("iterable") Tj 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (with) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (assertRaises) Tj 0 0 0 rg (\() Tj /F5 10 Tf .823529 .254902 .227451 rg (RuntimeError) Tj /F3 10 Tf 0 0 0 rg (\):) Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (C) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# Ambiguous dispatch: Iterable or Sized?) Tj T* ET
+n 72 0 324 12 re f*
+BT 1 0 0 1 0 74 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 .729412 .129412 .129412 rg ("sized") Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@g.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (collections) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Iterable) 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 (g_iterable) Tj 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 (return) Tj /F3 10 Tf 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("iterable") Tj 0 0 0 rg T* T* ( ) Tj 0 0 0 rg (g) Tj 0 0 0 rg (\() Tj 0 0 0 rg (C) Tj 0 0 0 rg (\(\)\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# RuntimeError: Ambiguous dispatch: Iterable or Sized?) Tj T* ET
Q
Q
Q
Q
Q
q
-1 0 0 1 62.69291 623.8236 cm
+1 0 0 1 62.69291 635.8236 cm
q
BT 1 0 0 1 0 14 Tm .745433 Tw 12 TL /F1 10 Tf 0 0 0 rg (This is consistent with the "refuse the temptation to guess" philosophy. ) Tj /F3 10 Tf 0 0 0 rg (functools.singledispatch) Tj T* 0 Tw /F1 10 Tf 0 0 0 rg (would raise a similar error.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 533.8236 cm
+1 0 0 1 62.69291 557.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 62 Tm /F1 10 Tf 12 TL .01104 Tw (It would be easy to rely on the order of registration to decide the precedence order. This is reasonable, but) Tj T* 0 Tw 3.788555 Tw (also fragile: if during some refactoring you change the registration order by mistake, a different) Tj T* 0 Tw 3.585814 Tw (implementation could be taken. If implementations of the generic functions are distributed across) Tj T* 0 Tw .939984 Tw (modules, and you change the import order, a different implementation could be taken. So the decorator) Tj T* 0 Tw .128935 Tw (module prefers to raise an error in the face of ambiguity. This is the same approach taken by the standard) Tj T* 0 Tw (library.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 491.8236 cm
q
-BT 1 0 0 1 0 74 Tm .01104 Tw 12 TL /F1 10 Tf 0 0 0 rg (It would be easy to rely on the order of registration to decide the precedence order. This is reasonable, but) Tj T* 0 Tw 3.788555 Tw (also fragile: if during some refactoring you change the registration order by mistake, a different) Tj T* 0 Tw 3.585814 Tw (implementation could be taken. If implementations of the generic functions are distributed across) Tj T* 0 Tw .939984 Tw (modules, and you change the import order, a different implementation could be taken. So the decorator) Tj T* 0 Tw .128935 Tw (module prefers to raise an error in the face of ambiguity. This is the same approach taken by the standard) Tj T* 0 Tw .471163 Tw (library. Notice that the dispatch algorithm used by the decorator module is different from the one used by) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (functools.singledispatch) Tj /F1 10 Tf 0 0 0 rg (, so there are cases where you will get different answers.) Tj T* ET
+BT 1 0 0 1 0 50 Tm .743735 Tw 12 TL /F1 10 Tf 0 0 0 rg (However, it should be noticed that the dispatch algorithm used by the decorator module is different from) Tj T* 0 Tw 2.269398 Tw (the one used by the standard library, so there are cases where you will get different answers. The) Tj T* 0 Tw 1.830814 Tw (difference is that ) Tj /F3 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (tries to insert the virtual ancestors ) Tj /F4 10 Tf (before ) Tj /F1 10 Tf (the base) Tj T* 0 Tw 1.149983 Tw (classes, whereas ) Tj /F3 10 Tf 0 0 0 rg (decorator.dispatch_on ) Tj /F1 10 Tf 0 0 0 rg (tries to insert them ) Tj /F4 10 Tf (after ) Tj /F1 10 Tf (the base classes. I will give an) Tj T* 0 Tw (example showing the difference:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 503.8236 cm
+1 0 0 1 62.69291 146.6236 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 336 re B*
+Q
+q
+.960784 .960784 .862745 rg
+n 0 312 18 12 re f*
+.960784 .960784 .862745 rg
+n 24 312 138 12 re f*
+.960784 .960784 .862745 rg
+n 162 312 18 12 re f*
+.960784 .960784 .862745 rg
+n 24 300 294 12 re f*
+.960784 .960784 .862745 rg
+n 24 288 84 12 re f*
+.960784 .960784 .862745 rg
+n 114 288 6 12 re f*
+.960784 .960784 .862745 rg
+n 126 288 66 12 re f*
+.960784 .960784 .862745 rg
+n 192 288 6 12 re f*
+.960784 .960784 .862745 rg
+n 198 288 30 12 re f*
+.960784 .960784 .862745 rg
+n 228 288 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 264 30 12 re f*
+.960784 .960784 .862745 rg
+n 60 264 6 12 re f*
+.960784 .960784 .862745 rg
+n 66 264 6 12 re f*
+.960784 .960784 .862745 rg
+n 72 264 36 12 re f*
+.960784 .960784 .862745 rg
+n 108 264 12 12 re f*
+.960784 .960784 .862745 rg
+n 48 252 24 12 re f*
+.960784 .960784 .862745 rg
+n 24 228 30 12 re f*
+.960784 .960784 .862745 rg
+n 60 228 6 12 re f*
+.960784 .960784 .862745 rg
+n 66 228 6 12 re f*
+.960784 .960784 .862745 rg
+n 72 228 6 12 re f*
+.960784 .960784 .862745 rg
+n 78 228 6 12 re f*
+.960784 .960784 .862745 rg
+n 84 228 30 12 re f*
+.960784 .960784 .862745 rg
+n 114 228 6 12 re f*
+.960784 .960784 .862745 rg
+n 126 228 6 12 re f*
+.960784 .960784 .862745 rg
+n 132 228 12 12 re f*
+.960784 .960784 .862745 rg
+n 48 216 18 12 re f*
+.960784 .960784 .862745 rg
+n 72 216 42 12 re f*
+.960784 .960784 .862745 rg
+n 114 216 6 12 re f*
+.960784 .960784 .862745 rg
+n 120 216 24 12 re f*
+.960784 .960784 .862745 rg
+n 144 216 12 12 re f*
+.960784 .960784 .862745 rg
+n 72 204 36 12 re f*
+.960784 .960784 .862745 rg
+n 114 204 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 180 90 12 re f*
+.960784 .960784 .862745 rg
+n 24 168 18 12 re f*
+.960784 .960784 .862745 rg
+n 48 168 6 12 re f*
+.960784 .960784 .862745 rg
+n 54 168 6 12 re f*
+.960784 .960784 .862745 rg
+n 60 168 18 12 re f*
+.960784 .960784 .862745 rg
+n 78 168 12 12 re f*
+.960784 .960784 .862745 rg
+n 48 156 36 12 re f*
+.960784 .960784 .862745 rg
+n 90 156 36 12 re f*
+.960784 .960784 .862745 rg
+n 24 132 66 12 re f*
+.960784 .960784 .862745 rg
+n 90 132 6 12 re f*
+.960784 .960784 .862745 rg
+n 96 132 6 12 re f*
+.960784 .960784 .862745 rg
+n 102 132 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 120 18 12 re f*
+.960784 .960784 .862745 rg
+n 48 120 18 12 re f*
+.960784 .960784 .862745 rg
+n 66 120 6 12 re f*
+.960784 .960784 .862745 rg
+n 72 120 18 12 re f*
+.960784 .960784 .862745 rg
+n 90 120 12 12 re f*
+.960784 .960784 .862745 rg
+n 48 108 36 12 re f*
+.960784 .960784 .862745 rg
+n 90 108 18 12 re f*
+.960784 .960784 .862745 rg
+n 24 84 66 12 re f*
+.960784 .960784 .862745 rg
+n 90 84 6 12 re f*
+.960784 .960784 .862745 rg
+n 96 84 6 12 re f*
+.960784 .960784 .862745 rg
+n 102 84 6 12 re f*
+.960784 .960784 .862745 rg
+n 108 84 54 12 re f*
+.960784 .960784 .862745 rg
+n 162 84 6 12 re f*
+.960784 .960784 .862745 rg
+n 24 72 18 12 re f*
+.960784 .960784 .862745 rg
+n 48 72 66 12 re f*
+.960784 .960784 .862745 rg
+n 114 72 6 12 re f*
+.960784 .960784 .862745 rg
+n 120 72 18 12 re f*
+.960784 .960784 .862745 rg
+n 138 72 12 12 re f*
+.960784 .960784 .862745 rg
+n 48 60 36 12 re f*
+.960784 .960784 .862745 rg
+n 90 60 66 12 re f*
+.960784 .960784 .862745 rg
+n 24 36 6 12 re f*
+.960784 .960784 .862745 rg
+n 36 36 6 12 re f*
+.960784 .960784 .862745 rg
+n 48 36 6 12 re f*
+.960784 .960784 .862745 rg
+n 54 36 12 12 re f*
+.960784 .960784 .862745 rg
+n 24 24 36 12 re f*
+.960784 .960784 .862745 rg
+n 66 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 72 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 78 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 84 24 6 12 re f*
+.960784 .960784 .862745 rg
+n 96 24 12 12 re f*
+.960784 .960784 .862745 rg
+n 114 24 18 12 re f*
+.960784 .960784 .862745 rg
+n 24 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 30 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 36 12 54 12 re f*
+.960784 .960784 .862745 rg
+n 90 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 96 12 48 12 re f*
+.960784 .960784 .862745 rg
+n 144 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 150 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 156 12 6 12 re f*
+.960784 .960784 .862745 rg
+n 174 12 246 12 re f*
+.960784 .960784 .862745 rg
+n 24 0 36 12 re f*
+.960784 .960784 .862745 rg
+n 66 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 72 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 78 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 84 0 6 12 re f*
+.960784 .960784 .862745 rg
+n 102 0 324 12 re f*
+BT 1 0 0 1 0 314 Tm 12 TL /F5 10 Tf 0 .501961 0 rg (def) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 1 rg (singledispatch_example2) Tj 0 0 0 rg (\(\):) Tj 0 0 0 rg T* ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# adapted from functools.singledispatch test case) Tj /F3 10 Tf 0 0 0 rg T* ( ) Tj 0 0 0 rg (singledispatch) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (dispatch_on) Tj 0 0 0 rg (\() Tj .729412 .129412 .129412 rg ('arg') Tj 0 0 0 rg (\)) Tj 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (S) 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 (pass) Tj /F3 10 Tf 0 0 0 rg T* T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (class) Tj /F3 10 Tf 0 0 0 rg ( ) Tj /F5 10 Tf 0 0 1 rg (V) Tj /F3 10 Tf 0 0 0 rg (\() Tj 0 0 0 rg (c) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Sized) Tj 0 0 0 rg (,) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (S) 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 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@singledispatch) 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 (j) Tj 0 0 0 rg (\() Tj 0 0 0 rg (arg) 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 .729412 .129412 .129412 rg ("base") Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@j.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (S) 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 (j_s) Tj 0 0 0 rg (\() Tj 0 0 0 rg (arg) 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 .729412 .129412 .129412 rg ("s") Tj 0 0 0 rg T* T* ( ) Tj .666667 .133333 1 rg (@j.register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (c) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Container) 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 (j_container) Tj 0 0 0 rg (\() Tj 0 0 0 rg (arg) 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 .729412 .129412 .129412 rg ("container") Tj 0 0 0 rg T* T* ( ) Tj 0 0 0 rg (v) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (=) Tj 0 0 0 rg ( ) Tj 0 0 0 rg (V) Tj 0 0 0 rg (\(\)) Tj 0 0 0 rg T* ( ) Tj /F5 10 Tf 0 .501961 0 rg (assert) Tj /F3 10 Tf 0 0 0 rg ( ) Tj 0 0 0 rg (j) Tj 0 0 0 rg (\() Tj 0 0 0 rg (v) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj .4 .4 .4 rg (==) Tj 0 0 0 rg ( ) Tj .729412 .129412 .129412 rg ("s") Tj 0 0 0 rg T* ( ) Tj 0 0 0 rg (c) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (Container) Tj .4 .4 .4 rg (.) Tj 0 0 0 rg (register) Tj 0 0 0 rg (\() Tj 0 0 0 rg (V) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# add c.Container to the virtual mro of V) 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 (j) Tj 0 0 0 rg (\() Tj 0 0 0 rg (v) Tj 0 0 0 rg (\)) Tj 0 0 0 rg ( ) Tj /F6 10 Tf .25098 .501961 .501961 rg (# "s", since the virtual mro is V, Sized, S, Container) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 102.6236 cm
+q
+BT 1 0 0 1 0 26 Tm 10.88816 Tw 12 TL /F1 10 Tf 0 0 0 rg (If you play with this example and replace the ) Tj /F3 10 Tf 0 0 0 rg (singledispatch ) Tj /F1 10 Tf 0 0 0 rg (definition with) Tj T* 0 Tw 1.433615 Tw /F3 10 Tf 0 0 0 rg (functools.singledispatch) Tj /F1 10 Tf 0 0 0 rg (, you will see the output change from ) Tj /F3 10 Tf 0 0 0 rg ("s" ) Tj /F1 10 Tf 0 0 0 rg (to ) Tj /F3 10 Tf 0 0 0 rg ("container") Tj /F1 10 Tf 0 0 0 rg (, because) Tj T* 0 Tw /F3 10 Tf 0 0 0 rg (functools.singledispatch ) Tj /F1 10 Tf 0 0 0 rg (will insert the ) Tj /F3 10 Tf 0 0 0 rg (Container ) Tj /F1 10 Tf 0 0 0 rg (class right before ) Tj /F3 10 Tf 0 0 0 rg (S) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+
+endstream
+endobj
+119 0 obj
+<< /Length 9358 >>
+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
q
BT 1 0 0 1 0 14 Tm .39561 Tw 12 TL /F1 10 Tf 0 0 0 rg (Finally let me notice that the decorator module implementation does not use any cache, whereas the one) Tj T* 0 Tw (in ) Tj /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 470.8236 cm
+1 0 0 1 62.69291 708.0236 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 440.8236 cm
+1 0 0 1 62.69291 678.0236 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
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .259431 Tw (One thing you should be aware of, is the performance penalty of decorators. The worse case is shown by) Tj T* 0 Tw (the following example:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 215.6236 cm
+1 0 0 1 62.69291 452.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -7419,13 +7633,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 195.6236 cm
+1 0 0 1 62.69291 432.8236 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 138.4236 cm
+1 0 0 1 62.69291 375.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -7446,27 +7660,20 @@ Q
Q
Q
q
-1 0 0 1 62.69291 94.42362 cm
+1 0 0 1 62.69291 331.6236 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
-118 0 obj
-<< /Length 14406 >>
-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 301.6236 cm
q
0 0 0 rg
BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .091984 Tw (More importantly, you should be aware that decorators will make your tracebacks longer and more difficult) Tj T* 0 Tw (to understand. Consider this example:) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 683.8236 cm
+1 0 0 1 62.69291 244.4236 cm
q
q
1 0 0 1 0 0 cm
@@ -7510,13 +7717,13 @@ Q
Q
Q
q
-1 0 0 1 62.69291 651.8236 cm
+1 0 0 1 62.69291 212.4236 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 522.6236 cm
+1 0 0 1 62.69291 83.22362 cm
q
q
1 0 0 1 0 0 cm
@@ -7663,32 +7870,39 @@ Q
Q
Q
Q
+
+endstream
+endobj
+120 0 obj
+<< /Length 13207 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 454.6236 cm
+1 0 0 1 62.69291 705.0236 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 328.6236 cm
+1 0 0 1 62.69291 579.0236 cm
q
BT 1 0 0 1 0 110 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 2.169398 Tw (maintaining the module and releasing new versions. It should be noticed that in Python 3.5 a lot of) Tj T* 0 Tw 9.189147 Tw (improvements have been made: in that version you can decorated a function with) Tj T* 0 Tw .084147 Tw /F3 10 Tf 0 0 0 rg (func_tools.update_wrapper ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F3 10 Tf 0 0 0 rg (pydoc ) Tj /F1 10 Tf 0 0 0 rg (will see the correct signature; still internally the function will) Tj T* 0 Tw 1.47748 Tw (have an incorrect signature, as you can see by using ) Tj /F3 10 Tf 0 0 0 rg (inspect.getfullargspec) Tj /F1 10 Tf 0 0 0 rg (: all documentation) Tj T* 0 Tw (tools using such function \(which has been correctly deprecated\) will see the wrong signature.) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 274.6236 cm
+1 0 0 1 62.69291 525.0236 cm
q
BT 1 0 0 1 0 38 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 2.15881 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 \(in Python 3.5 a lot of such) Tj T* 0 Tw (limitations have been removed\).) Tj T* ET
Q
Q
q
-1 0 0 1 62.69291 244.6236 cm
+1 0 0 1 62.69291 495.0236 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 127.4236 cm
+1 0 0 1 62.69291 377.8236 cm
q
q
1 0 0 1 0 0 cm
@@ -7790,21 +8004,14 @@ Q
Q
Q
q
-1 0 0 1 62.69291 95.42362 cm
+1 0 0 1 62.69291 345.8236 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
-
-endstream
-endobj
-119 0 obj
-<< /Length 7795 >>
-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
+1 0 0 1 62.69291 192.6236 cm
q
q
1 0 0 1 0 0 cm
@@ -7944,30 +8151,37 @@ Q
Q
Q
q
-1 0 0 1 62.69291 586.8236 cm
+1 0 0 1 62.69291 159.6236 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 568.8236 cm
+1 0 0 1 62.69291 141.6236 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 538.8236 cm
+1 0 0 1 62.69291 111.6236 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 532.8236 cm
+1 0 0 1 62.69291 105.6236 cm
Q
+
+endstream
+endobj
+121 0 obj
+<< /Length 2070 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
q
-1 0 0 1 62.69291 484.8236 cm
+1 0 0 1 62.69291 717.0236 cm
0 0 0 rg
BT /F1 10 Tf 12 TL ET
BT 1 0 0 1 0 2 Tm T* ET
@@ -7982,17 +8196,17 @@ q
Q
Q
q
-1 0 0 1 62.69291 484.8236 cm
+1 0 0 1 62.69291 717.0236 cm
Q
q
-1 0 0 1 62.69291 358.8236 cm
+1 0 0 1 62.69291 591.0236 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 328.8236 cm
+1 0 0 1 62.69291 561.0236 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
@@ -8001,71 +8215,74 @@ Q
endstream
endobj
-120 0 obj
-<< /Nums [ 0 121 0 R 1 122 0 R 2 123 0 R 3 124 0 R 4 125 0 R
- 5 126 0 R 6 127 0 R 7 128 0 R 8 129 0 R 9 130 0 R
- 10 131 0 R 11 132 0 R 12 133 0 R 13 134 0 R 14 135 0 R
- 15 136 0 R 16 137 0 R 17 138 0 R 18 139 0 R ] >>
+122 0 obj
+<< /Nums [ 0 123 0 R 1 124 0 R 2 125 0 R 3 126 0 R 4 127 0 R
+ 5 128 0 R 6 129 0 R 7 130 0 R 8 131 0 R 9 132 0 R
+ 10 133 0 R 11 134 0 R 12 135 0 R 13 136 0 R 14 137 0 R
+ 15 138 0 R 16 139 0 R 17 140 0 R 18 141 0 R 19 142 0 R ] >>
endobj
-121 0 obj
+123 0 obj
<< /S /D /St 1 >>
endobj
-122 0 obj
+124 0 obj
<< /S /D /St 2 >>
endobj
-123 0 obj
+125 0 obj
<< /S /D /St 3 >>
endobj
-124 0 obj
+126 0 obj
<< /S /D /St 4 >>
endobj
-125 0 obj
+127 0 obj
<< /S /D /St 5 >>
endobj
-126 0 obj
+128 0 obj
<< /S /D /St 6 >>
endobj
-127 0 obj
+129 0 obj
<< /S /D /St 7 >>
endobj
-128 0 obj
+130 0 obj
<< /S /D /St 8 >>
endobj
-129 0 obj
+131 0 obj
<< /S /D /St 9 >>
endobj
-130 0 obj
+132 0 obj
<< /S /D /St 10 >>
endobj
-131 0 obj
+133 0 obj
<< /S /D /St 11 >>
endobj
-132 0 obj
+134 0 obj
<< /S /D /St 12 >>
endobj
-133 0 obj
+135 0 obj
<< /S /D /St 13 >>
endobj
-134 0 obj
+136 0 obj
<< /S /D /St 14 >>
endobj
-135 0 obj
+137 0 obj
<< /S /D /St 15 >>
endobj
-136 0 obj
+138 0 obj
<< /S /D /St 16 >>
endobj
-137 0 obj
+139 0 obj
<< /S /D /St 17 >>
endobj
-138 0 obj
+140 0 obj
<< /S /D /St 18 >>
endobj
-139 0 obj
+141 0 obj
<< /S /D /St 19 >>
endobj
+142 0 obj
+<< /S /D /St 20 >>
+endobj
xref
-0 140
+0 143
0000000000 65535 f
0000000075 00000 n
0000000162 00000 n
@@ -8142,75 +8359,78 @@ xref
0000013282 00000 n
0000013494 00000 n
0000013706 00000 n
-0000013901 00000 n
-0000014132 00000 n
+0000013918 00000 n
+0000014113 00000 n
0000014344 00000 n
-0000014455 00000 n
-0000014703 00000 n
-0000014781 00000 n
-0000014898 00000 n
-0000015026 00000 n
-0000015168 00000 n
-0000015297 00000 n
-0000015439 00000 n
-0000015569 00000 n
-0000015704 00000 n
-0000015842 00000 n
-0000015979 00000 n
-0000016105 00000 n
-0000016239 00000 n
-0000016371 00000 n
-0000016512 00000 n
-0000016653 00000 n
-0000016806 00000 n
-0000016941 00000 n
-0000017098 00000 n
-0000017239 00000 n
-0000017351 00000 n
-0000017547 00000 n
-0000025168 00000 n
-0000032703 00000 n
-0000045267 00000 n
-0000061886 00000 n
-0000080467 00000 n
-0000098160 00000 n
-0000118574 00000 n
-0000137329 00000 n
-0000152039 00000 n
-0000166320 00000 n
-0000184835 00000 n
-0000201446 00000 n
-0000213852 00000 n
-0000230904 00000 n
-0000245146 00000 n
-0000258306 00000 n
-0000264567 00000 n
-0000279032 00000 n
-0000286885 00000 n
-0000287132 00000 n
-0000287170 00000 n
-0000287208 00000 n
-0000287246 00000 n
-0000287284 00000 n
-0000287322 00000 n
-0000287360 00000 n
-0000287398 00000 n
-0000287436 00000 n
-0000287474 00000 n
-0000287513 00000 n
-0000287552 00000 n
-0000287591 00000 n
-0000287630 00000 n
-0000287669 00000 n
-0000287708 00000 n
-0000287747 00000 n
-0000287786 00000 n
-0000287825 00000 n
+0000014556 00000 n
+0000014667 00000 n
+0000014915 00000 n
+0000014994 00000 n
+0000015111 00000 n
+0000015239 00000 n
+0000015381 00000 n
+0000015510 00000 n
+0000015652 00000 n
+0000015782 00000 n
+0000015917 00000 n
+0000016055 00000 n
+0000016192 00000 n
+0000016318 00000 n
+0000016452 00000 n
+0000016584 00000 n
+0000016725 00000 n
+0000016866 00000 n
+0000017019 00000 n
+0000017154 00000 n
+0000017311 00000 n
+0000017453 00000 n
+0000017566 00000 n
+0000017769 00000 n
+0000025390 00000 n
+0000032925 00000 n
+0000045489 00000 n
+0000062108 00000 n
+0000080689 00000 n
+0000098382 00000 n
+0000118796 00000 n
+0000137551 00000 n
+0000152264 00000 n
+0000166652 00000 n
+0000185167 00000 n
+0000201778 00000 n
+0000214193 00000 n
+0000231245 00000 n
+0000245487 00000 n
+0000258692 00000 n
+0000271400 00000 n
+0000280816 00000 n
+0000294082 00000 n
+0000296210 00000 n
+0000296468 00000 n
+0000296506 00000 n
+0000296544 00000 n
+0000296582 00000 n
+0000296620 00000 n
+0000296658 00000 n
+0000296696 00000 n
+0000296734 00000 n
+0000296772 00000 n
+0000296810 00000 n
+0000296849 00000 n
+0000296888 00000 n
+0000296927 00000 n
+0000296966 00000 n
+0000297005 00000 n
+0000297044 00000 n
+0000297083 00000 n
+0000297122 00000 n
+0000297161 00000 n
+0000297200 00000 n
trailer
<< /ID
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
- [(c\275h`3Y]|G{\321\020u\323\261\247) (c\275h`3Y]|G{\321\020u\323\261\247)]
- /Info 79 0 R /Root 78 0 R /Size 140 >>
+ [(\2036t\347"n8W\244\303vUDv\012\322) (\2036t\347"n8W\244\303vUDv\012\322)]
+ /Info 80 0 R /Root 79 0 R /Size 143 >>
startxref
-287864
+297239
%%EOF
diff --git a/documentation.rst b/documentation.rst
index 8927d4a..427487d 100644
--- a/documentation.rst
+++ b/documentation.rst
@@ -586,19 +586,20 @@ method, so that they can be used as decorators as in this example:
hello
AFTER
-The ``ba`` decorator is basically inserting a ``with ba:``
-block inside the function.
-However there two issues: the first is that ``GeneratorContextManager``
-objects are callable only in Python 3.2, so the previous example will break
-in older versions of Python; the second is that
-``GeneratorContextManager`` objects do not preserve the signature
-of the decorated functions: the decorated ``hello`` function here will have
-a generic signature ``hello(*args, **kwargs)`` but will break when
-called with more than zero arguments. For such reasons the decorator
-module, starting with release 3.4, offers a ``decorator.contextmanager``
-decorator that solves both problems and works in all supported Python versions.
-The usage is the same and factories decorated with ``decorator.contextmanager``
-will returns instances of ``ContextManager``, a subclass of
+The ``ba`` decorator is basically inserting a ``with ba:`` block
+inside the function. However there two issues: the first is that
+``GeneratorContextManager`` objects are callable only in Python 3.2,
+so the previous example will break in older versions of Python (you
+can solve this by installing ``contextlib2``); the second is that
+``GeneratorContextManager`` objects do not preserve the signature of
+the decorated functions: the decorated ``hello`` function here will
+have a generic signature ``hello(*args, **kwargs)`` but will break
+when called with more than zero arguments. For such reasons the
+decorator module, starting with release 3.4, offers a
+``decorator.contextmanager`` decorator that solves both problems and
+works in all supported Python versions. The usage is the same and
+factories decorated with ``decorator.contextmanager`` will returns
+instances of ``ContextManager``, a subclass of
``contextlib.GeneratorContextManager`` with a ``__call__`` method
acting as a signature-preserving decorator.
@@ -856,7 +857,7 @@ 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
+something concrete was done and now in Python 3.4 we have a decorator
``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
@@ -1054,7 +1055,7 @@ builtin ``len``, but you should get the idea.
Since in Python it is possible to consider any instance of ABCMeta
as a virtual ancestor of any other class (it is enough to register it
as ``ancestor.register(cls)``), any implementation of generic functions
-must take this feature into account. Let me give an example.
+must take virtual ancestors into account. Let me give an example.
Suppose you are using a third party set-like class like
the following:
@@ -1065,7 +1066,7 @@ the following:
# methods that make SomeSet set-like
# not shown ...
def __len__(self):
- return 0 # in reality one would return more than zero
+ return 0
Here the author of ``SomeSet`` made a mistake by not inheriting
@@ -1090,25 +1091,25 @@ Now, let us define an implementation of ``get_length`` specific to set:
The current implementation, as the one used by ``functools.singledispatch``,
-is able to discern that a ``Set`` is a ``Sized`` object, so the
+is able to discern that a ``Set`` is a ``Sized`` object, so the more specific
implementation for ``Set`` is taken:
.. code-block:: python
- >>> get_length(SomeSet())
+ >>> get_length(SomeSet()) # NB: the implementation for Sized would give 0
1
-Some times it is not clear how to dispatch. For instance, consider a
+Sometimes it is not clear how to dispatch. For instance, consider a
class ``C`` registered both as ``collections.Iterable`` and
``collections.Sized`` and define a generic function ``g`` with
implementations both for ``collections.Iterable`` and
``collections.Sized``. It is impossible to decide which implementation
-to use, since the ancestors are independent, and the following code
-will fail with a RuntimeError:
+to use, since the ancestors are independent, and the following function
+will raise a RuntimeError when called:
.. code-block:: python
- def singledispatch_example():
+ def singledispatch_example1():
singledispatch = dispatch_on('obj')
@singledispatch
@@ -1123,8 +1124,7 @@ will fail with a RuntimeError:
def g_iterable(object):
return "iterable"
- with assertRaises(RuntimeError):
- g(C()) # Ambiguous dispatch: Iterable or Sized?
+ g(C()) # RuntimeError: Ambiguous dispatch: Iterable or Sized?
This is consistent with the "refuse the temptation to guess"
@@ -1137,10 +1137,51 @@ implementation could be taken. If implementations of the generic
functions are distributed across modules, and you change the import
order, a different implementation could be taken. So the decorator
module prefers to raise an error in the face of ambiguity. This is the
-same approach taken by the standard library. Notice that the dispatch
+same approach taken by the standard library.
+
+However, it should be noticed that the dispatch
algorithm used by the decorator module is different from the one used
-by ``functools.singledispatch``, so there are cases where you will get
-different answers.
+by the standard library, so there are cases where you will get
+different answers. The difference is that ``functools.singledispatch``
+tries to insert the virtual ancestors *before* the base classes, whereas
+``decorator.dispatch_on`` tries to insert them *after* the base classes.
+I will give an example showing the difference:
+
+.. code-block:: python
+
+ def singledispatch_example2():
+ # adapted from functools.singledispatch test case
+ singledispatch = dispatch_on('arg')
+
+ class S(object):
+ pass
+
+ class V(c.Sized, S):
+ def __len__(self):
+ return 0
+
+ @singledispatch
+ def j(arg):
+ return "base"
+
+ @j.register(S)
+ def j_s(arg):
+ return "s"
+
+ @j.register(c.Container)
+ def j_container(arg):
+ return "container"
+
+ v = V()
+ assert j(v) == "s"
+ c.Container.register(V) # add c.Container to the virtual mro of V
+ return j(v) # "s", since the virtual mro is V, Sized, S, Container
+
+
+If you play with this example and replace the ``singledispatch`` definition
+with ``functools.singledispatch``, you will see the output change from ``"s"``
+to ``"container"``, because ``functools.singledispatch``
+will insert the ``Container`` class right before ``S``.
Finally let me notice that the decorator module implementation does
not use any cache, whereas the one in ``singledispatch`` has a cache.
@@ -1148,8 +1189,7 @@ not use any cache, whereas the one in ``singledispatch`` has a cache.
Caveats and limitations
-------------------------------------------
-The first thing you should be aware of, it the fact that decorators
-have a performance penalty.
+One thing you should be aware of, is the performance penalty of decorators.
The worse case is shown by the following example::
$ cat performance.sh
diff --git a/src/tests/documentation.py b/src/tests/documentation.py
index c5f8c7d..e0bc070 100644
--- a/src/tests/documentation.py
+++ b/src/tests/documentation.py
@@ -455,19 +455,20 @@ method, so that they can be used as decorators as in this example:
hello
AFTER
-The ``ba`` decorator is basically inserting a ``with ba:``
-block inside the function.
-However there two issues: the first is that ``GeneratorContextManager``
-objects are callable only in Python 3.2, so the previous example will break
-in older versions of Python; the second is that
-``GeneratorContextManager`` objects do not preserve the signature
-of the decorated functions: the decorated ``hello`` function here will have
-a generic signature ``hello(*args, **kwargs)`` but will break when
-called with more than zero arguments. For such reasons the decorator
-module, starting with release 3.4, offers a ``decorator.contextmanager``
-decorator that solves both problems and works in all supported Python versions.
-The usage is the same and factories decorated with ``decorator.contextmanager``
-will returns instances of ``ContextManager``, a subclass of
+The ``ba`` decorator is basically inserting a ``with ba:`` block
+inside the function. However there two issues: the first is that
+``GeneratorContextManager`` objects are callable only in Python 3.2,
+so the previous example will break in older versions of Python (you
+can solve this by installing ``contextlib2``); the second is that
+``GeneratorContextManager`` objects do not preserve the signature of
+the decorated functions: the decorated ``hello`` function here will
+have a generic signature ``hello(*args, **kwargs)`` but will break
+when called with more than zero arguments. For such reasons the
+decorator module, starting with release 3.4, offers a
+``decorator.contextmanager`` decorator that solves both problems and
+works in all supported Python versions. The usage is the same and
+factories decorated with ``decorator.contextmanager`` will returns
+instances of ``ContextManager``, a subclass of
``contextlib.GeneratorContextManager`` with a ``__call__`` method
acting as a signature-preserving decorator.
@@ -656,7 +657,7 @@ 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
+something concrete was done and now in Python 3.4 we have a decorator
``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
@@ -789,7 +790,7 @@ builtin ``len``, but you should get the idea.
Since in Python it is possible to consider any instance of ABCMeta
as a virtual ancestor of any other class (it is enough to register it
as ``ancestor.register(cls)``), any implementation of generic functions
-must take this feature into account. Let me give an example.
+must take virtual ancestors into account. Let me give an example.
Suppose you are using a third party set-like class like
the following:
@@ -813,23 +814,23 @@ Now, let us define an implementation of ``get_length`` specific to set:
$$get_length_set
The current implementation, as the one used by ``functools.singledispatch``,
-is able to discern that a ``Set`` is a ``Sized`` object, so the
+is able to discern that a ``Set`` is a ``Sized`` object, so the more specific
implementation for ``Set`` is taken:
.. code-block:: python
- >>> get_length(SomeSet())
+ >>> get_length(SomeSet()) # NB: the implementation for Sized would give 0
1
-Some times it is not clear how to dispatch. For instance, consider a
+Sometimes it is not clear how to dispatch. For instance, consider a
class ``C`` registered both as ``collections.Iterable`` and
``collections.Sized`` and define a generic function ``g`` with
implementations both for ``collections.Iterable`` and
``collections.Sized``. It is impossible to decide which implementation
-to use, since the ancestors are independent, and the following code
-will fail with a RuntimeError:
+to use, since the ancestors are independent, and the following function
+will raise a RuntimeError when called:
-$$singledispatch_example
+$$singledispatch_example1
This is consistent with the "refuse the temptation to guess"
philosophy. ``functools.singledispatch`` would raise a similar error.
@@ -841,10 +842,22 @@ implementation could be taken. If implementations of the generic
functions are distributed across modules, and you change the import
order, a different implementation could be taken. So the decorator
module prefers to raise an error in the face of ambiguity. This is the
-same approach taken by the standard library. Notice that the dispatch
+same approach taken by the standard library.
+
+However, it should be noticed that the dispatch
algorithm used by the decorator module is different from the one used
-by ``functools.singledispatch``, so there are cases where you will get
-different answers.
+by the standard library, so there are cases where you will get
+different answers. The difference is that ``functools.singledispatch``
+tries to insert the virtual ancestors *before* the base classes, whereas
+``decorator.dispatch_on`` tries to insert them *after* the base classes.
+I will give an example showing the difference:
+
+$$singledispatch_example2
+
+If you play with this example and replace the ``singledispatch`` definition
+with ``functools.singledispatch``, you will see the output change from ``"s"``
+to ``"container"``, because ``functools.singledispatch``
+will insert the ``Container`` class right before ``S``.
Finally let me notice that the decorator module implementation does
not use any cache, whereas the one in ``singledispatch`` has a cache.
@@ -852,8 +865,7 @@ not use any cache, whereas the one in ``singledispatch`` has a cache.
Caveats and limitations
-------------------------------------------
-The first thing you should be aware of, it the fact that decorators
-have a performance penalty.
+One thing you should be aware of, is the performance penalty of decorators.
The worse case is shown by the following example::
$ cat performance.sh
@@ -1072,6 +1084,7 @@ import time
import functools
import itertools
import collections
+import collections as c
from decorator import (decorator, decorate, FunctionMaker, contextmanager,
dispatch_on, __version__)
@@ -1434,7 +1447,7 @@ class SomeSet(collections.Sized):
# methods that make SomeSet set-like
# not shown ...
def __len__(self):
- return 0 # in reality one would return more than zero
+ return 0
@dispatch_on('obj')
@@ -1452,24 +1465,13 @@ def get_length_set(obj):
return 1
-@contextmanager
-def assertRaises(etype):
- """This works in Python 2.6 too"""
- try:
- yield
- except etype:
- pass
- else:
- raise Exception('Expected %s' % etype.__name__)
-
-
class C(object):
"Registered as Sized and Iterable"
collections.Sized.register(C)
collections.Iterable.register(C)
-def singledispatch_example():
+def singledispatch_example1():
singledispatch = dispatch_on('obj')
@singledispatch
@@ -1484,9 +1486,36 @@ def singledispatch_example():
def g_iterable(object):
return "iterable"
- with assertRaises(RuntimeError):
- g(C()) # Ambiguous dispatch: Iterable or Sized?
+ g(C()) # RuntimeError: Ambiguous dispatch: Iterable or Sized?
+
+
+def singledispatch_example2():
+ # adapted from functools.singledispatch test case
+ singledispatch = dispatch_on('arg')
+
+ class S(object):
+ pass
+
+ class V(c.Sized, S):
+ def __len__(self):
+ return 0
+
+ @singledispatch
+ def j(arg):
+ return "base"
+
+ @j.register(S)
+ def j_s(arg):
+ return "s"
+
+ @j.register(c.Container)
+ def j_container(arg):
+ return "container"
+ v = V()
+ assert j(v) == "s"
+ c.Container.register(V) # add c.Container to the virtual mro of V
+ return j(v) # "s", since the virtual mro is V, Sized, S, Container
if __name__ == '__main__':
import doctest
diff --git a/src/tests/test.py b/src/tests/test.py
index 2de144e..1e1cb3f 100644
--- a/src/tests/test.py
+++ b/src/tests/test.py
@@ -6,21 +6,37 @@ import decimal
import inspect
import functools
import collections
-from decorator import dispatch_on
+from decorator import dispatch_on, contextmanager
try:
from . import documentation as doc
except (SystemError, ValueError):
import documentation as doc
+@contextmanager
+def assertRaises(etype):
+ """This works in Python 2.6 too"""
+ try:
+ yield
+ except etype:
+ pass
+ else:
+ raise Exception('Expected %s' % etype.__name__)
+
+
class DocumentationTestCase(unittest.TestCase):
def test(self):
err = doctest.testmod(doc)[0]
self.assertEqual(err, 0)
- def test_singledispatch(self):
+ def test_singledispatch1(self):
+ if hasattr(functools, 'singledispatch'):
+ with assertRaises(RuntimeError):
+ doc.singledispatch_example1()
+
+ def test_singledispatch2(self):
if hasattr(functools, 'singledispatch'):
- doc.singledispatch_example()
+ self.assertEqual(doc.singledispatch_example2(), "s")
class ExtraTestCase(unittest.TestCase):
@@ -94,7 +110,7 @@ class TestSingleDispatch(unittest.TestCase):
def g(obj):
return "base"
- with doc.assertRaises(TypeError):
+ with assertRaises(TypeError):
# wrong number of arguments
@g.register(int)
def g_int():
@@ -259,7 +275,7 @@ class TestSingleDispatch(unittest.TestCase):
c.Iterable.register(O)
self.assertEqual(g(o), "sized")
c.Container.register(O)
- with doc.assertRaises(RuntimeError):
+ with assertRaises(RuntimeError): # was "sized" because in mro
self.assertEqual(g(o), "sized")
c.Set.register(O)
self.assertEqual(g(o), "set")
@@ -272,7 +288,7 @@ class TestSingleDispatch(unittest.TestCase):
self.assertEqual(g(p), "iterable")
c.Container.register(P)
- with doc.assertRaises(RuntimeError):
+ with assertRaises(RuntimeError):
self.assertEqual(g(p), "iterable")
class Q(c.Sized):
@@ -301,7 +317,7 @@ class TestSingleDispatch(unittest.TestCase):
# this ABC is implicitly registered on defaultdict which makes all of
# MutableMapping's bases implicit as well from defaultdict's
# perspective.
- with doc.assertRaises(RuntimeError):
+ with assertRaises(RuntimeError):
self.assertEqual(h(c.defaultdict(lambda: 0)), "sized")
class R(c.defaultdict):
@@ -320,8 +336,8 @@ class TestSingleDispatch(unittest.TestCase):
def i_sequence(arg):
return "sequence"
r = R()
- with doc.assertRaises(RuntimeError):
- self.assertEqual(i(r), "mapping")
+ with assertRaises(RuntimeError): # was no error
+ self.assertEqual(i(r), "sequence")
class S(object):
pass
@@ -338,37 +354,14 @@ class TestSingleDispatch(unittest.TestCase):
def __len__(self):
return 0
u = U()
- if sys.version >= '3':
- self.assertEqual(h(u), "sized")
- # implicit Sized subclass inferred
- # from the existence of __len__()
+ self.assertEqual(h(u), "sized")
+ # implicit Sized subclass inferred
+ # from the existence of __len__()
c.Container.register(U)
- # There is preference for registered versus inferred ABCs.
- with doc.assertRaises(RuntimeError):
- self.assertEqual(h(u), "sized")
-
- class V(c.Sized, S):
- def __len__(self):
- return 0
-
- @singledispatch
- def j(obj):
- return "base"
-
- @j.register(S)
- def j_s(arg):
- return "s"
-
- @j.register(c.Container)
- def j_container(arg):
- return "container"
- v = V()
- self.assertEqual(j(v), "s")
- c.Container.register(V)
- self.assertEqual(j(v), "s") # could be "container"
- # because it ends up right after
- # Sized in the MRO
+ # There is no preference for registered versus inferred ABCs.
+ with assertRaises(RuntimeError):
+ h(u)
if __name__ == '__main__':
unittest.main()