Deploying to gh-pages from @ python/peps@9475fa0aa4 🚀

This commit is contained in:
vstinner 2024-09-18 12:01:46 +00:00
commit e7a44a33a9
706 changed files with 431396 additions and 0 deletions

4
.buildinfo Normal file
View File

@ -0,0 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: a2c65ff4b368e636fe453f07402e58f4
tags: d77d1c0d9ca2f4c8421862c7c5a0d620

0
.nojekyll Normal file
View File

1
CNAME Normal file
View File

@ -0,0 +1 @@
peps.python.org

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
_images/pep-0458-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
_images/pep-0480-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

427
_images/pep-0495-fold.svg Normal file
View File

@ -0,0 +1,427 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="150mm"
height="140mm"
viewBox="0 0 531.49606 496.06299"
id="svg14800"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="pep-0495-fold.svg"
inkscape:export-filename="/Users/a/Work/peps/pep-0495-fold.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs14802">
<marker
inkscape:stockid="DotM"
orient="auto"
refY="0"
refX="0"
id="DotM"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6980"
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
transform="matrix(0.4,0,0,0.4,2.96,0.4)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="DiamondSstart"
orient="auto"
refY="0"
refX="0"
id="DiamondSstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path7010"
d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 0,-7.0710768 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
transform="matrix(0.2,0,0,0.2,1.2,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6943"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(-0.6,-0.6)"
inkscape:connector-curvature="0" />
</marker>
<pattern
inkscape:collect="always"
xlink:href="#pattern15623"
id="pattern15646"
patternTransform="translate(0,2.8515625e-5)" />
<pattern
inkscape:collect="always"
xlink:href="#Strips1_1"
id="pattern15599"
patternTransform="matrix(10,0,0,10,424.80508,-468.3217)" />
<pattern
inkscape:isstock="true"
inkscape:stockid="Stripes 1:1"
id="Strips1_1"
patternTransform="translate(0,0) scale(10,10)"
height="1"
width="2"
patternUnits="userSpaceOnUse"
inkscape:collect="always">
<rect
id="rect6108"
height="2"
width="1"
y="-0.5"
x="0"
style="fill:black;stroke:none" />
</pattern>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6916"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6919"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6925"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<pattern
patternUnits="userSpaceOnUse"
width="265.19116"
height="51.983494"
patternTransform="translate(-424.80508,468.3217)"
id="pattern15596">
<path
inkscape:connector-curvature="0"
id="path15588"
d="m 0.376692,25.991752 0,-25.61506 132.218888,0 132.21889,0 0,25.61506 0,25.61505 -132.21889,0 -132.218888,0 0,-25.61505 z"
style="opacity:0.5;fill:url(#pattern15599);fill-opacity:1;stroke:#ffd640;stroke-width:0.75338399;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:0.75338398, 0.75338398;stroke-dashoffset:0;stroke-opacity:1" />
</pattern>
<pattern
patternUnits="userSpaceOnUse"
width="213.59843"
height="36.4331"
patternTransform="translate(-0.5,1122.7283)"
id="pattern15623">
<path
inkscape:connector-curvature="0"
id="path15613"
d="m 0.5,0.5 212.59843,0 0,17.7166 -212.59843,0 z"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:10;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path15615"
d="m 0.5,18.2166 0,17.7165 212.59843,0 0,-17.7165"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:10;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path15617"
d="m 0.98017929,9.3247 0,-7.9105 105.47376071,0 105.47375,0 0,7.9105 0,7.9105 -105.47375,0 -105.47376071,0 0,-7.9105 z"
style="opacity:0.5;fill:#ffd744;fill-opacity:1;stroke:#ffd744;stroke-width:0.75338399;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:7.5338397;stroke-opacity:0.50196078" />
<path
inkscape:connector-curvature="0"
id="path15621"
d="m 0.98017929,27.0292 0,-8.2872 105.47376071,0 105.47375,0 0,8.2872 0,8.2872 -105.47375,0 -105.47376071,0 0,-8.2872 z"
style="opacity:0.5;fill:#326c9c;fill-opacity:1;stroke:#326c9b;stroke-width:0.75338399;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:7.5338397;stroke-opacity:0.50196078" />
</pattern>
<pattern
patternUnits="userSpaceOnUse"
width="213.59843"
height="36.433102"
patternTransform="translate(-0.5,1122.7283)"
id="pattern15643">
<rect
id="rect15629"
y="0"
x="0"
height="36.433102"
width="213.59843"
style="fill:url(#pattern15646);stroke:none" />
</pattern>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="93.8389"
inkscape:cy="200.6291"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="2556"
inkscape:window-height="1555"
inkscape:window-x="30"
inkscape:window-y="0"
inkscape:window-maximized="0"
objecttolerance="10000"
showborder="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<inkscape:grid
type="xygrid"
id="grid14808"
originx="37.568003"
spacingx="17.716536"
spacingy="17.716536"
empspacing="3"
originy="-71.39131" />
</sodipodi:namedview>
<metadata
id="metadata14805">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(37.568003,-484.90789)">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99921262;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)"
d="M 476.5503,945.88825 0,946.42873 0,521.76422"
id="path14810"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<flowRoot
xml:space="preserve"
id="flowRoot15458"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><flowRegion
id="flowRegion15460"><rect
id="rect15462"
width="159.44882"
height="106.29922"
x="-425.19687"
y="946.06299" /></flowRegion><flowPara
id="flowPara15464"></flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot15466"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><flowRegion
id="flowRegion15468"><rect
id="rect15470"
width="159.44882"
height="88.58268"
x="212.59843"
y="1070.0787"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;writing-mode:lr-tb;text-anchor:middle" /></flowRegion><flowPara
id="flowPara15474"></flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot15480"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><flowRegion
id="flowRegion15482"><rect
id="rect15484"
width="70.866142"
height="53.149609"
x="212.59843"
y="1105.5118" /></flowRegion><flowPara
id="flowPara15486"></flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot15488"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(270.90867,-112.71393)"><flowRegion
id="flowRegion15490"><rect
id="rect15492"
width="265.74805"
height="88.58268"
x="159.44882"
y="1070.0787"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;writing-mode:lr-tb;text-anchor:start" /></flowRegion><flowPara
id="flowPara15496">UTC</flowPara></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-570.61304"
y="-20.473276"
id="text15498"
sodipodi:linespacing="125%"
transform="matrix(0,-1,1,0,0,0)"><tspan
sodipodi:role="line"
id="tspan15500"
x="-570.61304"
y="-20.473276">local</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#336d9c;stroke-width:2.12598419;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 52.152923,893.91006 266.74473,679.31828"
id="path15502"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#336d9c;stroke-width:2.12598419;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 265.74804,733.46456 425.19686,574.01574"
id="path15504"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 12;stroke-dashoffset:0;stroke-opacity:1"
d="m 0,733.46456 265.74804,0 0,211.88321"
id="path15552"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99921262;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.9992126, 11.99055118;stroke-dashoffset:0;stroke-opacity:1"
d="m 0,680.31496 318.89765,0 0,265.57329"
id="path15566"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99921262;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.99921262, 7.99370098;stroke-dashoffset:0;stroke-opacity:1"
d="m 212.59843,733.46456 0,212.42369"
id="path15676"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#336d9c;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 12;stroke-dashoffset:0;stroke-opacity:1"
d="m 265.74804,680.31496 0,53.1496 z"
id="path15678"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:6, 2;stroke-dashoffset:0;stroke-opacity:1"
d="m 0,698.03149 248.0315,0 0,247.85676"
id="path15680"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4, 2;stroke-dashoffset:0;stroke-opacity:1"
d="m 248.0315,698.03149 53.14961,0 0,247.85676"
id="path15682"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<text
xml:space="preserve"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Italic';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-17.04035"
y="703.841"
id="text16422"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16424"
x="-17.04035"
y="703.841">t</tspan></text>
<text
xml:space="preserve"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Italic';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="240.81497"
y="962.27954"
id="text16438"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16440"
x="240.81497"
y="962.27954">u<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan16442">0</tspan></tspan></text>
<text
xml:space="preserve"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Italic';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="294.96457"
y="963.77954"
id="text16444"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16446"
x="294.96457"
y="963.77954">u<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan16448">1</tspan></tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#336d9c;stroke-width:2.12598419;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 212.59843,946.06299 53.14961,0"
id="path16450"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#336d9c;stroke-width:2.12598419;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 0,733.46456 0,-53.1496"
id="path16452"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffd847;stroke-width:2.12598419;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 265.74804,946.06299 53.14961,0"
id="path16454"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffd847;stroke-width:2.12598419;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 2.216536,733.46456 0,-53.1496"
id="path16456"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:20px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold Italic';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="343.96481"
y="712.6087"
id="text16458"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16460"
x="343.96481"
y="712.6087">Fold</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#336d9c;stroke-width:2.12598425;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="m 265.74804,680.31492 0,53.14961"
id="path16481"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

1
_images/pep-0495-gap.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

BIN
_images/pep-0525-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 15 KiB

BIN
_images/pep-3147-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

580
_images/process_flow.svg Normal file
View File

@ -0,0 +1,580 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.0"
width="518.000000pt"
height="230.000000pt"
viewBox="0 0 518.000000 230.000000"
preserveAspectRatio="xMidYMid meet"
id="svg3789"
sodipodi:docname="pep-0001-1.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)">
<metadata
id="metadata3795">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3793">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker26466"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path26464"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker24282"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path24280" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker18063"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path18061" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker16749"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path16747"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker15177"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path15175" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker14679"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path14677"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker13779"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path13777" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker12309"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path12307"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker11613"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path11611" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker9945"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path9943"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5313"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5311" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path4732"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4726"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.8) rotate(180) translate(12.5,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker5033"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path5031"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4723"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.8) translate(12.5,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4744"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" />
</marker>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1376"
id="namedview3791"
showgrid="false"
inkscape:zoom="1.7126796"
inkscape:cx="356.07349"
inkscape:cy="132.46132"
inkscape:window-x="3200"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg3789"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
position="10.509846,117.79787"
orientation="1,0"
id="guide4717"
inkscape:locked="false" />
<sodipodi:guide
position="88.019964,219.39306"
orientation="0,1"
id="guide4719"
inkscape:locked="false" />
<sodipodi:guide
position="416.89059,151.51696"
orientation="0,1"
id="guide21702"
inkscape:locked="false" />
<sodipodi:guide
position="219.83096,105.97429"
orientation="0,1"
id="guide21704"
inkscape:locked="false" />
<sodipodi:guide
position="254.42587,56.052518"
orientation="0,1"
id="guide21706"
inkscape:locked="false" />
</sodipodi:namedview>
<g
id="g4690"
transform="translate(-95.026522,-3.0384519)">
<rect
id="rect4612"
width="127"
height="37"
x="194.48441"
y="61.797592"
style="fill:none;stroke:#000000;stroke-width:1.125;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<text
id="text4622"
y="88.499252"
x="198.61234"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.75px"
y="88.499252"
x="198.61234"
id="tspan4620"
sodipodi:role="line">Provisional</tspan></text>
</g>
<g
id="g4675"
transform="translate(-0.490154,-0.39305957)">
<rect
id="rect4606"
width="127"
height="37"
x="11"
y="11"
style="fill:none;stroke:#000000;stroke-width:1.125;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;image-rendering:auto" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="45.952637"
y="37.70166"
id="text4630"><tspan
id="tspan4632"
sodipodi:role="line"
x="45.952637"
y="37.70166"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.75px">Draft</tspan></text>
</g>
<g
id="g4700"
transform="translate(26.712527,-17.52529)">
<rect
id="rect4616"
width="127"
height="37"
x="194.92232"
y="172.58888"
style="fill:none;stroke:#000000;stroke-width:1.125;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="199.76997"
y="199.29054"
id="text4638"><tspan
sodipodi:role="line"
id="tspan4636"
x="199.76997"
y="199.29054"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.75px">Withdrawn</tspan></text>
</g>
<g
id="g4695"
transform="translate(-20.143873,-6.5596308)">
<rect
style="fill:none;stroke:#000000;stroke-width:1.125;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
y="113.471"
x="180.90918"
height="37"
width="127"
id="rect4614" />
<text
id="text4642"
y="138.04034"
x="196.46143"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.75px"
y="138.04034"
x="196.46143"
id="tspan4640"
sodipodi:role="line">Rejected</tspan></text>
</g>
<g
id="g4710"
transform="translate(2.9753917,-0.39303668)">
<rect
style="fill:none;stroke:#000000;stroke-width:1.125;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
y="11"
x="371"
height="37"
width="127"
id="rect3797" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="409.07324"
y="37.70166"
id="text4646"><tspan
sodipodi:role="line"
id="tspan4644"
x="409.07324"
y="37.70166"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.75px">Final</tspan></text>
</g>
<g
id="g4685"
transform="translate(-1.7850301,-1.7067669)">
<rect
style="fill:none;stroke:#000000;stroke-width:1.125;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
y="12.31373"
x="192.29486"
height="37"
width="127"
id="rect4610" />
<text
id="text4650"
y="36.883068"
x="205.44623"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.75px"
y="36.883068"
x="205.44623"
id="tspan4648"
sodipodi:role="line">Accepted</tspan></text>
</g>
<g
id="g4680"
transform="translate(-0.490154,12.699399)">
<rect
style="fill:none;stroke:#000000;stroke-width:1.125;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
y="173"
x="11"
height="37"
width="127"
id="rect4608" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="26.165527"
y="199.70166"
id="text4654"><tspan
sodipodi:role="line"
id="tspan4652"
x="26.165527"
y="199.70166"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.75px">Deferred</tspan></text>
</g>
<flowRoot
xml:space="preserve"
id="flowRoot4656"
style="fill:black;stroke:none;stroke-opacity:1;stroke-width:1px;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:1;font-family:sans-serif;font-style:normal;font-weight:normal;font-size:40px;line-height:125%;letter-spacing:0px;word-spacing:0px"><flowRegion
id="flowRegion4658"><rect
id="rect4660"
width="8.7582054"
height="81.743256"
x="99.843544"
y="115.73779" /></flowRegion><flowPara
id="flowPara4662" /></flowRoot> <g
id="g4715"
transform="translate(2.9753917,12.699399)">
<rect
id="rect4604"
width="127"
height="37"
x="371"
y="173"
style="fill:none;stroke:#000000;stroke-width:1.125;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="400.96826"
y="199.70166"
id="text4666"><tspan
sodipodi:role="line"
id="tspan4664"
x="400.96826"
y="199.70166"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.75px">Active</tspan></text>
</g>
<g
id="g4705"
transform="translate(0,7.4535255)">
<rect
style="fill:none;stroke:#000000;stroke-width:1.125;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
y="90.699661"
x="374.46555"
height="37"
width="127"
id="rect4618" />
<text
id="text4670"
y="115.269"
x="387.37521"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:22px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.75px"
y="115.269"
x="379"
id="tspan4668"
sodipodi:role="line">Superseded</tspan></text>
</g>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
d="M 17.515858,48.274259 V 183.04703"
id="path4721"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path5309"
d="M 26.545549,185.99111 V 49.504289"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5313)" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.00000001, 1.5;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9945)"
d="M 439.22346,47.398438 V 96.65244"
id="path9941"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker12309)"
d="m 137.13596,29.727733 h 52.04728"
id="path12305"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path13775"
d="M 318.43082,27.538182 H 370.4781"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker13779)" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker14679)"
d="M 69.843993,48.540525 V 77.774512 H 97.059211"
id="path14669"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path15173"
d="M 55.952177,47.433136 V 123.87614 H 158.23713"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker15177)" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker16749)"
d="M 42.113037,47.312202 V 173.81084 H 220.13598"
id="path16745"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path18059"
d="M 226.35002,69.110911 H 403.09174 V 50.174148"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker18063)" />
<path
inkscape:connector-curvature="0"
id="path24278"
d="m 226.85286,85.449036 h 29.78208 v 20.112814"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.00000001,1.5;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker24282)" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.00000001,1.5;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker26466)"
d="M 226.44001,77.758634 H 316.6304 V 153.39305"
id="path26462"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 27 KiB

35
_static/colour_scheme.js Normal file
View File

@ -0,0 +1,35 @@
// Handle setting and changing the site's color scheme (light/dark)
"use strict";
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)")
const getColourScheme = () => document.documentElement.dataset.colour_scheme
const setColourScheme = (colourScheme = getColourScheme()) => {
document.documentElement.dataset.colour_scheme = colourScheme
localStorage.setItem("colour_scheme", colourScheme)
setPygments(colourScheme)
}
// Map system theme to a cycle of steps
const cycles = {
dark: ["auto", "light", "dark"], // auto (dark) → light → dark
light: ["auto", "dark", "light"], // auto (light) → dark → light
}
const nextColourScheme = (colourScheme = getColourScheme()) => {
const cycle = cycles[prefersDark.matches ? "dark" : "light"]
return cycle[(cycle.indexOf(colourScheme) + 1) % cycle.length]
}
const setPygments = (colourScheme = getColourScheme()) => {
const pygmentsDark = document.getElementById("pyg-dark")
const pygmentsLight = document.getElementById("pyg-light")
pygmentsDark.disabled = colourScheme === "light"
pygmentsLight.disabled = colourScheme === "dark"
pygmentsDark.media = colourScheme === "auto" ? "(prefers-color-scheme: dark)" : ""
pygmentsLight.media = colourScheme === "auto" ? "(prefers-color-scheme: light)" : ""
}
// Update Pygments state (the page theme is initialised inline, see page.html)
document.addEventListener("DOMContentLoaded", () => setColourScheme())

165
_static/mq.css Normal file
View File

@ -0,0 +1,165 @@
@charset "UTF-8";
/* Media Queries */
/* Reduce padding & margins for smaller screens */
@media (max-width: 40em) {
section#pep-page-section {
padding: 1rem;
}
section#pep-page-section > header > h1 {
padding-right: 0;
border-right: none;
}
ul.breadcrumbs {
padding: 0 0 .5rem;
}
nav#pep-sidebar {
display: none;
}
pre {
font-size: 0.8175rem;
}
table th,
table td {
padding: 0 0.1rem;
}
}
@media (min-width: 40em) {
section#pep-page-section {
display: table;
margin: 0 auto;
max-width: 75em;
padding: 0.5rem 1rem 0;
width: 100%;
}
section#pep-page-section > article {
max-width: 37em;
width: 74%;
float: right;
margin-right: 0;
font-size: 1rem;
}
nav#pep-sidebar {
width: 24%;
float: left;
margin-right: 2%;
}
/* Make less prominent when sidebar ToC is available */
details > summary {
font-size: 1rem;
width: max-content;
}
}
@media (min-width: 60em) {
section#pep-page-section > article {
max-width: 56em;
padding-left: 3.2%;
padding-right: 3.2%;
}
}
@media print {
*,
*:before,
*:after {
color: #000 !important;
}
body {
font-size: 10pt;
line-height: 1.67;
}
*[role="main"] a[href]:after {
content: " (" attr(href) ")";
font-size: .75rem;
}
pre,
blockquote {
page-break-inside: avoid;
}
thead {
display: table-header-group;
}
tr,
img {
page-break-inside: avoid;
}
img {
max-width: 100% !important;
}
/* Page margins according to DIN 5008, leaves space for punched holes. */
@page {
margin-top: 2cm;
margin-bottom: 2cm;
margin-left: 2.5cm;
margin-right: 2.5cm;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h1,
h2,
h3 {
page-break-after: avoid;
}
h1 {
font-size: 18pt;
font-weight: bold;
text-align: center;
}
h2, details > summary {
font-size: 15pt;
font-weight: normal;
}
h3 {
font-size: 13pt;
font-weight: normal;
}
h4 {
font-size: 10pt;
font-weight: 600;
}
a, abbr {
text-decoration: none;
}
details {
display: none;
}
details[open] {
display: block;
}
h1.page-title:first-child {
margin-top: 0;
}
section#pep-page-section {
display: flex;
justify-content: center;
padding: 0;
margin: 0 auto;
}
section#pep-page-section > header,
nav#pep-sidebar {
display: none;
}
section#pep-page-section > article {
float: none;
max-width: 17.5cm;
width: auto;
margin: 0;
padding: 0;
}
/* This blocks a small portion on each page. */
readthedocs-flyout {
display: none;
}
}

BIN
_static/og-image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
_static/py.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

84
_static/pygments.css Normal file
View File

@ -0,0 +1,84 @@
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f8f8f8; }
.highlight .c { color: #8f5902; font-style: italic } /* Comment */
.highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */
.highlight .g { color: #000000 } /* Generic */
.highlight .k { color: #204a87; font-weight: bold } /* Keyword */
.highlight .l { color: #000000 } /* Literal */
.highlight .n { color: #000000 } /* Name */
.highlight .o { color: #ce5c00; font-weight: bold } /* Operator */
.highlight .x { color: #000000 } /* Other */
.highlight .p { color: #000000; font-weight: bold } /* Punctuation */
.highlight .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #8f5902; font-style: italic } /* Comment.Preproc */
.highlight .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */
.highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */
.highlight .gd { color: #a40000 } /* Generic.Deleted */
.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */
.highlight .ges { color: #000000; font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #ef2929 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #000000; font-style: italic } /* Generic.Output */
.highlight .gp { color: #8f5902 } /* Generic.Prompt */
.highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */
.highlight .kc { color: #204a87; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #204a87; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #204a87; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #204a87; font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { color: #204a87; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #204a87; font-weight: bold } /* Keyword.Type */
.highlight .ld { color: #000000 } /* Literal.Date */
.highlight .m { color: #0000cf; font-weight: bold } /* Literal.Number */
.highlight .s { color: #4e9a06 } /* Literal.String */
.highlight .na { color: #c4a000 } /* Name.Attribute */
.highlight .nb { color: #204a87 } /* Name.Builtin */
.highlight .nc { color: #000000 } /* Name.Class */
.highlight .no { color: #000000 } /* Name.Constant */
.highlight .nd { color: #5c35cc; font-weight: bold } /* Name.Decorator */
.highlight .ni { color: #ce5c00 } /* Name.Entity */
.highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #000000 } /* Name.Function */
.highlight .nl { color: #f57900 } /* Name.Label */
.highlight .nn { color: #000000 } /* Name.Namespace */
.highlight .nx { color: #000000 } /* Name.Other */
.highlight .py { color: #000000 } /* Name.Property */
.highlight .nt { color: #204a87; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #000000 } /* Name.Variable */
.highlight .ow { color: #204a87; font-weight: bold } /* Operator.Word */
.highlight .pm { color: #000000; font-weight: bold } /* Punctuation.Marker */
.highlight .w { color: #f8f8f8 } /* Text.Whitespace */
.highlight .mb { color: #0000cf; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000cf; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000cf; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000cf; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000cf; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #4e9a06 } /* Literal.String.Affix */
.highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */
.highlight .sc { color: #4e9a06 } /* Literal.String.Char */
.highlight .dl { color: #4e9a06 } /* Literal.String.Delimiter */
.highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #4e9a06 } /* Literal.String.Double */
.highlight .se { color: #4e9a06 } /* Literal.String.Escape */
.highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */
.highlight .si { color: #4e9a06 } /* Literal.String.Interpol */
.highlight .sx { color: #4e9a06 } /* Literal.String.Other */
.highlight .sr { color: #4e9a06 } /* Literal.String.Regex */
.highlight .s1 { color: #4e9a06 } /* Literal.String.Single */
.highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */
.highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #000000 } /* Name.Function.Magic */
.highlight .vc { color: #000000 } /* Name.Variable.Class */
.highlight .vg { color: #000000 } /* Name.Variable.Global */
.highlight .vi { color: #000000 } /* Name.Variable.Instance */
.highlight .vm { color: #000000 } /* Name.Variable.Magic */
.highlight .il { color: #0000cf; font-weight: bold } /* Literal.Number.Integer.Long */

85
_static/pygments_dark.css Normal file
View File

@ -0,0 +1,85 @@
pre { line-height: 125%; }
td.linenos .normal { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #404040 }
.highlight { background: #202020; color: #d0d0d0 }
.highlight .c { color: #ababab; font-style: italic } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .esc { color: #d0d0d0 } /* Escape */
.highlight .g { color: #d0d0d0 } /* Generic */
.highlight .k { color: #6ebf26; font-weight: bold } /* Keyword */
.highlight .l { color: #d0d0d0 } /* Literal */
.highlight .n { color: #d0d0d0 } /* Name */
.highlight .o { color: #d0d0d0 } /* Operator */
.highlight .x { color: #d0d0d0 } /* Other */
.highlight .p { color: #d0d0d0 } /* Punctuation */
.highlight .ch { color: #ababab; font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: #ababab; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #ff3a3a; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #ababab; font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: #ababab; font-style: italic } /* Comment.Single */
.highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */
.highlight .gd { color: #ff3a3a } /* Generic.Deleted */
.highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */
.highlight .ges { color: #d0d0d0; font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #ff3a3a } /* Generic.Error */
.highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #589819 } /* Generic.Inserted */
.highlight .go { color: #cccccc } /* Generic.Output */
.highlight .gp { color: #aaaaaa } /* Generic.Prompt */
.highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */
.highlight .gt { color: #ff3a3a } /* Generic.Traceback */
.highlight .kc { color: #6ebf26; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #6ebf26; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #6ebf26; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #6ebf26 } /* Keyword.Pseudo */
.highlight .kr { color: #6ebf26; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #6ebf26; font-weight: bold } /* Keyword.Type */
.highlight .ld { color: #d0d0d0 } /* Literal.Date */
.highlight .m { color: #51b2fd } /* Literal.Number */
.highlight .s { color: #ed9d13 } /* Literal.String */
.highlight .na { color: #bbbbbb } /* Name.Attribute */
.highlight .nb { color: #2fbccd } /* Name.Builtin */
.highlight .nc { color: #71adff; text-decoration: underline } /* Name.Class */
.highlight .no { color: #40ffff } /* Name.Constant */
.highlight .nd { color: #ffa500 } /* Name.Decorator */
.highlight .ni { color: #d0d0d0 } /* Name.Entity */
.highlight .ne { color: #bbbbbb } /* Name.Exception */
.highlight .nf { color: #71adff } /* Name.Function */
.highlight .nl { color: #d0d0d0 } /* Name.Label */
.highlight .nn { color: #71adff; text-decoration: underline } /* Name.Namespace */
.highlight .nx { color: #d0d0d0 } /* Name.Other */
.highlight .py { color: #d0d0d0 } /* Name.Property */
.highlight .nt { color: #6ebf26; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #40ffff } /* Name.Variable */
.highlight .ow { color: #6ebf26; font-weight: bold } /* Operator.Word */
.highlight .pm { color: #d0d0d0 } /* Punctuation.Marker */
.highlight .w { color: #666666 } /* Text.Whitespace */
.highlight .mb { color: #51b2fd } /* Literal.Number.Bin */
.highlight .mf { color: #51b2fd } /* Literal.Number.Float */
.highlight .mh { color: #51b2fd } /* Literal.Number.Hex */
.highlight .mi { color: #51b2fd } /* Literal.Number.Integer */
.highlight .mo { color: #51b2fd } /* Literal.Number.Oct */
.highlight .sa { color: #ed9d13 } /* Literal.String.Affix */
.highlight .sb { color: #ed9d13 } /* Literal.String.Backtick */
.highlight .sc { color: #ed9d13 } /* Literal.String.Char */
.highlight .dl { color: #ed9d13 } /* Literal.String.Delimiter */
.highlight .sd { color: #ed9d13 } /* Literal.String.Doc */
.highlight .s2 { color: #ed9d13 } /* Literal.String.Double */
.highlight .se { color: #ed9d13 } /* Literal.String.Escape */
.highlight .sh { color: #ed9d13 } /* Literal.String.Heredoc */
.highlight .si { color: #ed9d13 } /* Literal.String.Interpol */
.highlight .sx { color: #ffa500 } /* Literal.String.Other */
.highlight .sr { color: #ed9d13 } /* Literal.String.Regex */
.highlight .s1 { color: #ed9d13 } /* Literal.String.Single */
.highlight .ss { color: #ed9d13 } /* Literal.String.Symbol */
.highlight .bp { color: #2fbccd } /* Name.Builtin.Pseudo */
.highlight .fm { color: #71adff } /* Name.Function.Magic */
.highlight .vc { color: #40ffff } /* Name.Variable.Class */
.highlight .vg { color: #40ffff } /* Name.Variable.Global */
.highlight .vi { color: #40ffff } /* Name.Variable.Instance */
.highlight .vm { color: #40ffff } /* Name.Variable.Magic */
.highlight .il { color: #51b2fd } /* Literal.Number.Integer.Long */

38
_static/sticky_banner.js Normal file
View File

@ -0,0 +1,38 @@
"use strict";
// Inject a style element into the document head that adds scroll-margin-top to
// all elements with an id attribute. This is used to offset the scroll position
// when clicking on a link to an element with an id attribute. The offset is
// equal to the height of the sticky banner.
document.addEventListener("DOMContentLoaded", () => {
const stickyBanners = document.getElementsByClassName("sticky-banner");
if (!stickyBanners.length) {
return;
}
const stickyBanner = stickyBanners[0];
const node = document.createElement("style");
node.id = "sticky-banner-style";
document.head.appendChild(node);
function adjustBannerMargin() {
const text = document.createTextNode(
":target { scroll-margin-top: " + stickyBanner.offsetHeight + "px; }"
);
node.replaceChildren(text);
}
const closeButton = document.querySelector('.close-button');
if (closeButton) {
closeButton.addEventListener('click', () => {
const stickyBanner = document.querySelector('.sticky-banner');
if (stickyBanner) {
stickyBanner.style.display = 'none';
}
});
}
adjustBannerMargin();
document.addEventListener("resize", adjustBannerMargin);
document.addEventListener("load", adjustBannerMargin);
});

468
_static/style.css Normal file
View File

@ -0,0 +1,468 @@
@charset "UTF-8";
/* Styles for PEPs */
/*
* `initial` works like undefined variables, so `var(initial, x)` will resolve to `x`.
* A space means an empty value, so `var( , x) y` will resolve to `y`.
*/
@media (prefers-color-scheme: dark) {
:root {
--light: ;
--dark: initial;
}
}
@media (prefers-color-scheme: light) {
:root {
--dark: ;
--light: initial;
}
}
:root[data-colour_scheme="dark"] {
--light: ;
--dark: initial;
}
:root[data-colour_scheme="light"] {
--dark: ;
--light: initial;
}
/* Set master colours */
:root {
--colour-background: var(--light, white) var(--dark, #111);
--colour-background-accent-strong: var(--light, #ccc) var(--dark, #444);
--colour-background-accent-medium: var(--light, #ddd) var(--dark, #333);
--colour-background-accent-light: var(--light, #eee) var(--dark, #222);
--colour-text: var(--light, #333) var(--dark, #ccc);
--colour-text-strong: var(--light, #222) var(--dark, #ddd);
--colour-links: var(--light, #069) var(--dark, #8bf);
--colour-links-light: var(--light, #057) var(--dark, #acf);
--colour-scrollbar: var(--light, #ccc) var(--dark, #333);
--colour-rule-strong: var(--light, #888) var(--dark, #777);
--colour-rule-light: var(--light, #ddd) var(--dark, #222);
--colour-inline-code-bg: var(--light, #eee) var(--dark, #333);
--colour-inline-code-text: var(--light, #222) var(--dark, #ccc);
--colour-error: var(--light, #faa) var(--dark, #800);
--colour-warning: var(--light, #fca) var(--dark, #840);
--colour-caution: var(--light, #ffa) var(--dark, #550);
--colour-attention: var(--light, #bdf) var(--dark, #045);
--colour-tip: var(--light, #bfc) var(--dark, #041);
}
img.invert-in-dark-mode {
filter: var(--dark, invert(1) hue-rotate(.5turn));
}
/* Set master rules */
* {box-sizing: border-box}
:root {color-scheme: light dark}
html {
overflow-y: scroll;
line-height: 1.5;
font-size: 1rem;
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
}
body {
margin: 0;
color: var(--colour-text);
background-color: var(--colour-background);
}
section#pep-page-section {
padding: 0.25rem;
}
/* This is likely very close to the browser default, but we make it a variable
* so it can be used in other rules. */
:root {
--paragraph-margin-vertical: 1em;
}
p {
margin: var(--paragraph-margin-vertical) 0;
}
/* Header rules */
h1 {
font-size: 2rem;
font-weight: bold;
}
h2 {
font-size: 1.6rem;
font-weight: bold;
}
h3 {
font-size: 1.4rem;
font-weight: normal;
}
h4 {
font-size: 1.2rem;
font-weight: normal;
}
h5,
h6 {
font-size: 1rem;
font-weight: bold;
}
/* Anchor link rules */
a,
a:active,
a:visited {
color: var(--colour-links);
display: inline;
overflow-wrap: anywhere;
text-decoration-color: var(--colour-background-accent-strong);
}
a:hover,
a:focus {
text-decoration-color: var(--colour-rule-strong);
}
/* Blockquote rules */
blockquote {
font-style: italic;
border-left: 1px solid var(--colour-rule-strong);
padding: .5rem 1rem;
}
blockquote em {
font-style: normal;
}
cite {
font-style: italic;
}
/* Code rules (code literals and Pygments highlighting blocks) */
code,
pre {
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
font-size: 0.875rem;
-webkit-hyphens: none;
hyphens: none;
}
code {
overflow-wrap: anywhere;
}
code.literal {
background-color: var(--colour-inline-code-bg);
color: var(--colour-inline-code-text);
font-size: .8em;
padding: 1px 2px 1px;
}
pre {
overflow-x: auto;
padding: .5rem .75rem;
white-space: pre;
}
.good pre {
border-left: 3px solid rgba(74, 182, 93, 1);
}
.bad pre {
border-left: 3px solid rgb(244, 76, 78);
}
.maybe pre {
border-left: 3px solid rgb(244, 227, 76);
}
/* Contents rules */
details > summary {
cursor: pointer;
font-size: 1.6rem;
font-weight: bold;
margin-bottom: 1em;
}
details > summary:hover {
text-decoration: underline;
}
/* Definition list rules */
dl dt {
font-weight: bold;
}
dl dd {
margin-bottom: 0.5rem;
}
/* Horizontal rule rule */
hr {
border: 0;
border-top: 1px solid var(--colour-rule-light);
}
/* Image rules */
img {
max-width: 100%;
}
a img {
display: block;
margin: 0 auto;
}
/* List rules */
ol.loweralpha {list-style: lower-alpha}
ol.upperalpha {list-style: upper-alpha}
ol.lowerroman {list-style: lower-roman}
ol.upperroman {list-style: upper-roman}
/* We can't express this as a single rule using `not(.simple)`, because when a
* simple list is nested inside another simple list, the inner list is not given
* a class. So instead we use two rules, one more specific than the other. */
#pep-content ol li,
#pep-content ul li {
margin: var(--paragraph-margin-vertical) 0;
}
#pep-content ol.simple li,
#pep-content ul.simple li {
margin: 0 0;
}
/* Maths rules */
sub,
sup {
font-size: .75em;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {top: -0.5em}
sub {bottom: -0.25em}
/* Table rules */
div.table-wrapper {
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
border: 1px solid var(--colour-background-accent-strong);
}
table caption {
margin: 1rem 0 .75rem;
}
table thead tr {
background-color: var(--colour-background-accent-medium);
color: var(--colour-text-strong);
}
table tbody tr {
border-top: 1px solid var(--colour-background-accent-strong);
}
table th,
table td {
text-align: left;
padding: 0.25rem 0.5rem 0.2rem;
}
table.pep-zero-table tr td:nth-child(1),
table.pep-zero-table tr td:nth-child(2) {
white-space: nowrap;
}
table th + th,
table td + td {
border-left: 1px solid var(--colour-background-accent-strong);
}
/* Common column widths for PEP status tables */
table.pep-zero-table tr td:nth-child(1) {
width: 5%;
}
table.pep-zero-table tr td:nth-child(2) {
width: 7%;
}
table.pep-zero-table tr td:nth-child(3),
table.pep-zero-table tr td:nth-child(4){
width: 41%;
}
table.pep-zero-table tr td:nth-child(5) {
width: 6%;
}
/* Authors & Sponsors table */
#authors-owners table td,
#authors-owners table th {
width: 50%;
}
/* Breadcrumbs rules */
section#pep-page-section > header {
border-bottom: 1px solid var(--colour-rule-light);
}
section#pep-page-section > header > h1 {
font-size: 1.1rem;
margin: 0;
display: inline-block;
padding-right: .6rem;
border-right: 1px solid var(--colour-rule-strong);
}
ul.breadcrumbs {
margin: 0;
padding: .5rem 0 .5rem .4rem;
list-style: none;
display: inline-block;
}
ul.breadcrumbs li {
display: inline;
}
ul.breadcrumbs a {
text-decoration: none;
}
/* Dark mode toggle rules */
#colour-scheme-cycler {
background: transparent;
border: none;
padding: 0;
cursor: pointer;
width: 1.2rem;
height: 1.2rem;
float: right;
transform: translate(0, 50%);
}
#colour-scheme-cycler svg {
color: var(--colour-rule-strong);
height: 1.2rem;
width: 1.2rem;
display: none;
}
:root[data-colour_scheme="auto"] #colour-scheme-cycler svg.colour-scheme-icon-when-auto {display: initial}
:root[data-colour_scheme="dark"] #colour-scheme-cycler svg.colour-scheme-icon-when-dark {display: initial}
:root[data-colour_scheme="light"] #colour-scheme-cycler svg.colour-scheme-icon-when-light {display: initial}
/* Admonitions rules */
div.admonition {
background-color: var(--colour-background-accent-medium);
margin-bottom: 1rem;
margin-top: 1rem;
padding: 0.5rem 0.75rem;
}
div.admonition a {
color: var(--colour-links-light);
}
div.danger,
div.error {
background-color: var(--colour-error);
}
div.warning {
background-color: var(--colour-warning);
}
div.attention,
div.caution {
background-color: var(--colour-caution);
}
div.important {
background-color: var(--colour-attention);
}
div.hint,
div.tip {
background-color: var(--colour-tip);
}
p.admonition-title {
font-weight: bold;
}
/* PEP Header / references rules */
dl.rfc2822,
dl.footnote {
display: grid;
grid-template-columns: fit-content(30%) auto;
width: 100%;
}
dl.footnote {
border-top: 1px solid var(--colour-rule-strong);
line-height: 1.875;
}
dl.rfc2822 > dt,
dl.rfc2822 > dd {
padding: .1rem .3rem .1rem;
}
dl.footnote > dt,
dl.footnote > dd {
padding: .25rem .5rem .2rem;
border-bottom: 1px solid var(--colour-rule-strong);
}
dl.rfc2822 > dt {
text-align: right;
}
dl.footnote > dt {
font-weight: normal;
border-right: 1px solid var(--colour-background);
}
dl.rfc2822 > dd,
dl.footnote > dd {
margin: 0;
}
/* Sidebar formatting */
#pep-sidebar {
overflow-y: auto;
position: sticky;
top: 0;
height: 100vh;
}
#pep-sidebar > h2 {
font-size: 1.4rem;
}
#contents ol,
#contents ul,
#pep-sidebar ol,
#pep-sidebar ul {
padding: 0;
margin: 0 0 0 1.5rem;
}
#pep-sidebar ul {
font-size: .9rem;
margin-left: 1rem;
}
#pep-sidebar ul a {
text-decoration: none;
}
#source {
padding-bottom: 2rem;
font-weight: bold;
}
.reference.external > strong {
font-weight: normal; /* Fix strong links for :pep: and :rfc: roles */
}
.visually-hidden {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip-path: polygon(0px 0px, 0px 0px,0px 0px, 0px 0px) !important;
white-space: nowrap !important;
border: 0 !important;
}
/* Sticky banners */
/* Default styles, sticky for larger screens */
.sticky-banner {
top: 0;
position: sticky;
z-index: 1;
}
/* Override for smaller screens, non-sticky */
@media (max-width: 600px) {
.sticky-banner {
position: static;
padding: 5px;
font-size: 12px;
}
}
.close-button {
cursor: pointer;
position: absolute;
top: 0;
right: 0;
padding: 0.5em;
font-size: 1.5em;
border: none;
background: transparent;
color: inherit;
margin-top: 0;
}

30
_static/wrap_tables.js Normal file
View File

@ -0,0 +1,30 @@
// Wrap the tables in PEP bodies in a div, to allow for responsive scrolling
"use strict";
const pepContentId = "pep-content";
// Wrap passed table element in wrapper divs
function wrapTable (table) {
const wrapper = document.createElement("div");
wrapper.classList.add("table-wrapper");
table.parentNode.insertBefore(wrapper, table);
wrapper.appendChild(table);
}
// Wrap all tables in the PEP content in wrapper divs
function wrapPepContentTables () {
const pepContent = document.getElementById(pepContentId);
const bodyTables = pepContent.getElementsByTagName("table");
Array.from(bodyTables).forEach(wrapTable);
}
// Wrap the tables as soon as the DOM is loaded
document.addEventListener("DOMContentLoaded", () => {
if (document.getElementById(pepContentId)) {
wrapPepContentTables();
}
})

183
api/index.html Normal file
View File

@ -0,0 +1,183 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEPs API | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/api/index/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEPs API | peps.python.org'>
<meta property="og:description" content="">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/api/index/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEPs API</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="peps-api">
<h1>PEPs API</h1>
<p>There is a read-only API of published PEPs available at:</p>
<ul class="simple">
<li><a class="reference external" href="https://peps.python.org/api/peps.json">https://peps.python.org/api/peps.json</a></li>
</ul>
<p>The structure is like:</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;&lt;PEP number&gt;&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;number&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">integer</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;title&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;authors&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;discussions_to&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;status&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Accepted&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;Active&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;Deferred&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;Draft&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;Final&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;Provisional&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;Rejected&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;Superseded&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;Withdrawn&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;type&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Informational&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;Process&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;Standards Track&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;topic&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;governance&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;packaging&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;release&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;typing&quot;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">&quot;&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;created&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;python_version&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;post_history&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;resolution&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;requires&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;replaces&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;superseded_by&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;url&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">string</span>
<span class="w"> </span><span class="p">},</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Date values are formatted as DD-MMM-YYYY,
and multiple dates are combined in a comma-separated list.</p>
<p>For example:</p>
<div class="highlight-json notranslate"><div class="highlight"><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;8&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;number&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">8</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Style Guide for Python Code&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;authors&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Guido van Rossum, Barry Warsaw, Alyssa Coghlan&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;discussions_to&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Active&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Process&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;topic&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;created&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;05-Jul-2001&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;python_version&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;post_history&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;05-Jul-2001, 01-Aug-2013&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;resolution&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;requires&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;replaces&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;superseded_by&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;url&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;https://peps.python.org/pep-0008/&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;484&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;number&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">484</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Type Hints&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;authors&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Guido van Rossum, Jukka Lehtosalo, Łukasz Langa&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;discussions_to&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;python-dev@python.org&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Final&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Standards Track&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;topic&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;typing&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;created&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;29-Sep-2014&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;python_version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;3.5&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;post_history&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;16-Jan-2015, 20-Mar-2015, 17-Apr-2015, 20-May-2015, 22-May-2015&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;resolution&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;https://mail.python.org/pipermail/python-dev/2015-May/140104.html&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;requires&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;replaces&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;superseded_by&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;url&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;https://peps.python.org/pep-0484/&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;622&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;number&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">622</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Structural Pattern Matching&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;authors&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Brandt Bucher, Daniel F Moisset, Tobias Kohn, Ivan Levkivskyi, Guido van Rossum, Talin&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;discussions_to&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;python-dev@python.org&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Superseded&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Standards Track&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;topic&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;created&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;23-Jun-2020&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;python_version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;3.10&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;post_history&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;23-Jun-2020, 08-Jul-2020&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;resolution&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;requires&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;replaces&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;superseded_by&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;634&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;url&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;https://peps.python.org/pep-0622/&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/api/index.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

11154
api/peps.json Normal file

File diff suppressed because it is too large Load Diff

104
contents/index.html Normal file
View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>Python Enhancement Proposals (PEPs) | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/contents/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='Python Enhancement Proposals (PEPs) | peps.python.org'>
<meta property="og:description" content="">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/contents/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>Python Enhancement Proposals (PEPs)</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="python-enhancement-proposals-peps">
<h1>Python Enhancement Proposals (PEPs)</h1>
<p>This is an internal Sphinx page; please go to the <a class="reference internal" href="../pep-0000/"><span class="doc">PEP Index</span></a>.</p>
<div class="toctree-wrapper compound">
</div>
</section>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul class="simple">
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/contents.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

9207
index.html Normal file

File diff suppressed because it is too large Load Diff

BIN
objects.inv Normal file

Binary file not shown.

9207
pep-0000/index.html Normal file

File diff suppressed because it is too large Load Diff

847
pep-0001/index.html Normal file
View File

@ -0,0 +1,847 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 1 PEP Purpose and Guidelines | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0001/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 1 PEP Purpose and Guidelines | peps.python.org'>
<meta property="og:description" content="Python Enhancement Proposals (PEPs)">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0001/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python Enhancement Proposals (PEPs)">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 1</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 1 PEP Purpose and Guidelines</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Barry Warsaw, Jeremy Hylton, David Goodger, Alyssa Coghlan</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">13-Jun-2000</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd">21-Mar-2001, 29-Jul-2002, 03-May-2003, 05-May-2012,
07-Apr-2013</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#what-is-a-pep">What is a PEP?</a></li>
<li><a class="reference internal" href="#pep-audience">PEP Audience</a></li>
<li><a class="reference internal" href="#pep-types">PEP Types</a></li>
<li><a class="reference internal" href="#pep-workflow">PEP Workflow</a><ul>
<li><a class="reference internal" href="#python-s-steering-council">Pythons Steering Council</a></li>
<li><a class="reference internal" href="#python-s-core-developers">Pythons Core Developers</a></li>
<li><a class="reference internal" href="#python-s-bdfl">Pythons BDFL</a></li>
<li><a class="reference internal" href="#pep-editors">PEP Editors</a></li>
<li><a class="reference internal" href="#start-with-an-idea-for-python">Start with an idea for Python</a></li>
<li><a class="reference internal" href="#submitting-a-pep">Submitting a PEP</a></li>
<li><a class="reference internal" href="#discussing-a-pep">Discussing a PEP</a></li>
<li><a class="reference internal" href="#pep-review-resolution">PEP Review &amp; Resolution</a></li>
<li><a class="reference internal" href="#pep-maintenance">PEP Maintenance</a></li>
</ul>
</li>
<li><a class="reference internal" href="#what-belongs-in-a-successful-pep">What belongs in a successful PEP?</a></li>
<li><a class="reference internal" href="#pep-formats-and-templates">PEP Formats and Templates</a></li>
<li><a class="reference internal" href="#pep-header-preamble">PEP Header Preamble</a></li>
<li><a class="reference internal" href="#auxiliary-files">Auxiliary Files</a></li>
<li><a class="reference internal" href="#changing-existing-peps">Changing Existing PEPs</a></li>
<li><a class="reference internal" href="#transferring-pep-ownership">Transferring PEP Ownership</a></li>
<li><a class="reference internal" href="#pep-editor-responsibilities-workflow">PEP Editor Responsibilities &amp; Workflow</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="what-is-a-pep">
<h2><a class="toc-backref" href="#what-is-a-pep" role="doc-backlink">What is a PEP?</a></h2>
<p>PEP stands for Python Enhancement Proposal. A PEP is a design
document providing information to the Python community, or describing
a new feature for Python or its processes or environment. The PEP
should provide a concise technical specification of the feature and a
rationale for the feature.</p>
<p>We intend PEPs to be the primary mechanisms for proposing major new
features, for collecting community input on an issue, and for
documenting the design decisions that have gone into Python. The PEP
author is responsible for building consensus within the community and
documenting dissenting opinions.</p>
<p>Because the PEPs are maintained as text files in a versioned
repository, their revision history is the historical record of the
feature proposal. This historical record is available by the normal git
commands for retrieving older revisions, and can also be browsed
<a class="reference external" href="https://github.com/python/peps">on GitHub</a>.</p>
</section>
<section id="pep-audience">
<h2><a class="toc-backref" href="#pep-audience" role="doc-backlink">PEP Audience</a></h2>
<p>The typical primary audience for PEPs are the core developers of the CPython
reference interpreter and their elected Steering Council, as well as developers
of other implementations of the Python language specification.</p>
<p>However, other parts of the Python community may also choose to use the process
(particularly for Informational PEPs) to document expected API conventions and
to manage complex design coordination problems that require collaboration across
multiple projects.</p>
</section>
<section id="pep-types">
<h2><a class="toc-backref" href="#pep-types" role="doc-backlink">PEP Types</a></h2>
<p>There are three kinds of PEP:</p>
<ol class="arabic simple">
<li>A <strong>Standards Track</strong> PEP describes a new feature or implementation
for Python. It may also describe an interoperability standard that will
be supported outside the standard library for current Python versions
before a subsequent PEP adds standard library support in a future
version.</li>
<li>An <strong>Informational</strong> PEP describes a Python design issue, or
provides general guidelines or information to the Python community,
but does not propose a new feature. Informational PEPs do not
necessarily represent a Python community consensus or
recommendation, so users and implementers are free to ignore
Informational PEPs or follow their advice.</li>
<li>A <strong>Process</strong> PEP describes a process surrounding Python, or
proposes a change to (or an event in) a process. Process PEPs are
like Standards Track PEPs but apply to areas other than the Python
language itself. They may propose an implementation, but not to
Pythons codebase; they often require community consensus; unlike
Informational PEPs, they are more than recommendations, and users
are typically not free to ignore them. Examples include
procedures, guidelines, changes to the decision-making process, and
changes to the tools or environment used in Python development.
Any meta-PEP is also considered a Process PEP.</li>
</ol>
</section>
<section id="pep-workflow">
<h2><a class="toc-backref" href="#pep-workflow" role="doc-backlink">PEP Workflow</a></h2>
<section id="python-s-steering-council">
<h3><a class="toc-backref" href="#python-s-steering-council" role="doc-backlink">Pythons Steering Council</a></h3>
<p>There are several references in this PEP to the “Steering Council” or “Council”.
This refers to the current members of the elected Steering Council described
in <a class="pep reference internal" href="../pep-0013/" title="PEP 13 Python Language Governance">PEP 13</a>, in their role as the final authorities on whether or not PEPs
will be accepted or rejected.</p>
</section>
<section id="python-s-core-developers">
<h3><a class="toc-backref" href="#python-s-core-developers" role="doc-backlink">Pythons Core Developers</a></h3>
<p>There are several references in this PEP to “core developers”. This refers to
the currently active Python core team members described in <a class="pep reference internal" href="../pep-0013/" title="PEP 13 Python Language Governance">PEP 13</a>.</p>
</section>
<section id="python-s-bdfl">
<h3><a class="toc-backref" href="#python-s-bdfl" role="doc-backlink">Pythons BDFL</a></h3>
<p>Previous versions of this PEP used the title “BDFL-Delegate” for PEP decision
makers. This was a historical reference to Pythons previous governance model,
where all design authority ultimately derived from Guido van Rossum, the
original creator of the Python programming language. By contrast, the Steering
Councils design authority derives from their election by the currently active
core developers. Now, PEP-Delegate is used in place of BDFL-Delegate.</p>
</section>
<section id="pep-editors">
<h3><a class="toc-backref" href="#pep-editors" role="doc-backlink">PEP Editors</a></h3>
<p>The PEP editors are individuals responsible for managing the administrative
and editorial aspects of the PEP workflow (e.g. assigning PEP numbers and
changing their status). See <a class="reference internal" href="#pep-editor-responsibilities-workflow">PEP Editor Responsibilities &amp; Workflow</a> for
details.</p>
<p>PEP editorship is by invitation of the current editors, and they can be
contacted by mentioning <code class="docutils literal notranslate"><span class="pre">&#64;python/pep-editors</span></code> on GitHub. All of the PEP
workflow can be conducted via the GitHub <a class="reference external" href="https://github.com/python/peps">PEP repository</a> issues and pull
requests.</p>
</section>
<section id="start-with-an-idea-for-python">
<h3><a class="toc-backref" href="#start-with-an-idea-for-python" role="doc-backlink">Start with an idea for Python</a></h3>
<p>The PEP process begins with a new idea for Python. It is highly
recommended that a single PEP contain a single key proposal or new
idea; the more focused the PEP, the more successful it tends to be.
Most enhancements and bug fixes dont need a PEP and
can be submitted directly to the <a class="reference external" href="https://github.com/python/cpython/issues">Python issue tracker</a>.
The PEP editors reserve the
right to reject PEP proposals if they appear too unfocused or too
broad. If in doubt, split your PEP into several well-focused ones.</p>
<p>Each PEP must have a champion someone who writes the PEP using the style
and format described below, shepherds the discussions in the appropriate
forums, and attempts to build community consensus around the idea. The PEP
champion (a.k.a. Author) should first attempt to ascertain whether the idea is
PEP-able. Posting to the <a class="reference external" href="https://discuss.python.org/c/ideas/">Ideas category</a> of the <a class="reference external" href="https://discuss.python.org/">Python Discourse</a> is usually
the best way to go about this, unless a more specialized venue is appropriate,
such as the <a class="reference external" href="https://discuss.python.org/c/typing/">Typing category</a> (for static typing ideas)
or <a class="reference external" href="https://discuss.python.org/c/packaging/">Packaging category</a> (for packaging ideas) on the Python Discourse.</p>
<p>Vetting an idea publicly before going as far as writing a PEP is meant
to save the potential author time. Many ideas have been brought
forward for changing Python that have been rejected for various
reasons. Asking the Python community first if an idea is original
helps prevent too much time being spent on something that is
guaranteed to be rejected based on prior discussions (searching
the internet does not always do the trick). It also helps to make sure
the idea is applicable to the entire community and not just the author.
Just because an idea sounds good to the author does not
mean it will work for most people in most areas where Python is used.</p>
<p>Once the champion has asked the Python community as to whether an
idea has any chance of acceptance, a draft PEP should be presented to
the appropriate venue mentioned above.
This gives the author a chance to flesh out the draft
PEP to make properly formatted, of high quality, and to address
initial concerns about the proposal.</p>
</section>
<section id="submitting-a-pep">
<h3><a class="toc-backref" href="#submitting-a-pep" role="doc-backlink">Submitting a PEP</a></h3>
<p>Following the above initial discussion, the workflow varies based on whether
any of the PEPs co-authors are core developers. If one or more of the PEPs
co-authors are core developers, they are responsible for following the process
outlined below. Otherwise (i.e. none of the co-authors are core developers),
then the PEP author(s) will need to find a sponsor for the PEP.</p>
<p>Ideally, a core developer sponsor is identified, but non-core sponsors may also
be selected with the approval of the Steering Council. Members of the GitHub
“PEP editors” team and members of the Typing Council (<a class="pep reference internal" href="../pep-0729/" title="PEP 729 Typing governance process">PEP 729</a>) are
pre-approved to be sponsors. The sponsors job is to
provide guidance to the PEP author to help them through the logistics of the
PEP process (somewhat acting like a mentor). Being a sponsor does <strong>not</strong>
disqualify that person from becoming a co-author or PEP-Delegate later on (but
not both). The sponsor of a PEP is recorded in the “Sponsor:” field of the
header.</p>
<p>Once the sponsor or the core developer(s) co-authoring the PEP deem the PEP
ready for submission, the proposal should be submitted as a draft PEP via a
<a class="reference external" href="https://github.com/python/peps/pulls">GitHub pull request</a>. The draft must be written in PEP style as described
below, else it will fail review immediately (although minor errors may be
corrected by the editors).</p>
<p>The standard PEP workflow is:</p>
<ul>
<li>You, the PEP author, fork the <a class="reference external" href="https://github.com/python/peps">PEP repository</a>, and create a file named
<code class="file docutils literal notranslate"><span class="pre">pep-</span><em><span class="pre">NNNN</span></em><span class="pre">.rst</span></code> that contains your new PEP. <code class="samp docutils literal notranslate"><em><span class="pre">NNNN</span></em></code> should be the next
available PEP number not used by a published or in-PR PEP.</li>
<li>In the “PEP:” header field, enter the PEP number that matches your filename
as your draft PEP number.</li>
<li>In the “Type:” header field, enter “Standards Track”,
“Informational”, or “Process” as appropriate, and for the “Status:”
field enter “Draft”. For full details, see <a class="reference internal" href="#pep-header-preamble">PEP Header Preamble</a>.</li>
<li>Update <a class="reference external" href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners">.github/CODEOWNERS</a> such that any co-author(s) or sponsors
with write access to the <a class="reference external" href="https://github.com/python/peps">PEP repository</a> are listed for your new file.
This ensures any future pull requests changing the file will be assigned
to them.</li>
<li>Push this to your GitHub fork and submit a pull request.</li>
<li>The PEP editors review your PR for structure, formatting, and other
errors. For a reST-formatted PEP, <a class="pep reference internal" href="../pep-0012/" title="PEP 12 Sample reStructuredText PEP Template">PEP 12</a> is provided as a template.
It also provides a complete introduction to reST markup that is used
in PEPs. Approval criteria are:<ul class="simple">
<li>It is sound and complete. The ideas must make technical sense. The
editors do not consider whether they seem likely to be accepted.</li>
<li>The title accurately describes the content.</li>
<li>The PEPs language (spelling, grammar, sentence structure, etc.)
and code style (examples should match <a class="pep reference internal" href="../pep-0007/" title="PEP 7 Style Guide for C Code">PEP 7</a> &amp; <a class="pep reference internal" href="../pep-0008/" title="PEP 8 Style Guide for Python Code">PEP 8</a>) should be
correct and conformant. The PEP text will be automatically checked for
correct reStructuredText formatting when the pull request is submitted.
PEPs with invalid reST markup will not be approved.</li>
</ul>
<p>Editors are generally quite lenient about this initial review,
expecting that problems will be corrected by the reviewing process.
<strong>Note:</strong> Approval of the PEP is no guarantee that there are no
embarrassing mistakes! Correctness is the responsibility of authors
and reviewers, not the editors.</p>
<p>If the PEP isnt ready for approval, an editor will send it back to
the author for revision, with specific instructions.</p>
</li>
<li>Once approved, they will assign your PEP a number.</li>
</ul>
<p>Once the review process is complete, and the PEP editors approve it (note that
this is <em>not</em> the same as accepting your PEP!), they will squash commit your
pull request onto main.</p>
<p>The PEP editors will not unreasonably deny publication of a PEP. Reasons for
denying PEP status include duplication of effort, being technically unsound,
not providing proper motivation or addressing backwards compatibility, or not
in keeping with the Python philosophy. The Steering Council can be consulted
during the approval phase, and are the final arbiter of a drafts PEP-ability.</p>
<p>Developers with write access to the <a class="reference external" href="https://github.com/python/peps">PEP repository</a> may claim PEP
numbers directly by creating and committing a new PEP. When doing so, the
developer must handle the tasks that would normally be taken care of by the
PEP editors (see <a class="reference internal" href="#pep-editor-responsibilities-workflow">PEP Editor Responsibilities &amp; Workflow</a>). This includes
ensuring the initial version meets the expected standards for submitting a
PEP. Alternately, even developers should submit PEPs via pull request.
When doing so, you are generally expected to handle the process yourself;
if you need assistance from PEP editors, mention <code class="docutils literal notranslate"><span class="pre">&#64;python/pep-editors</span></code>
on GitHub.</p>
<p>As updates are necessary, the PEP author can check in new versions if they
(or a collaborating developer) have write access to the <a class="reference external" href="https://github.com/python/peps">PEP repository</a>.
Getting a PEP number assigned early can be useful for ease of
reference, especially when multiple draft PEPs are being considered at the
same time.</p>
<p>Standards Track PEPs consist of two parts, a design document and a
reference implementation. It is generally recommended that at least a
prototype implementation be co-developed with the PEP, as ideas that sound
good in principle sometimes turn out to be impractical when subjected to the
test of implementation.</p>
</section>
<section id="discussing-a-pep">
<h3><a class="toc-backref" href="#discussing-a-pep" role="doc-backlink">Discussing a PEP</a></h3>
<p>As soon as a PEP number has been assigned
and the draft PEP is committed to the <a class="reference external" href="https://github.com/python/peps">PEP repository</a>,
a discussion thread for the PEP should be created
to provide a central place to discuss and review its contents, and the
PEP should be updated so that the <code class="docutils literal notranslate"><span class="pre">Discussions-To</span></code> header links to it.</p>
<p>The PEP authors (or sponsor, if applicable) may select any reasonable venue
for the discussion, so long as the the following criteria are met:</p>
<ul class="simple">
<li>The forum is appropriate to the PEPs topic.</li>
<li>The thread is publicly available on the web so that all interested parties
can participate.</li>
<li>The discussion is subject to the <a class="reference external" href="https://www.python.org/psf/conduct/">Python Community Code of Conduct</a>.</li>
<li>A direct link to the current discussion thread is provided in the PEP
under the <code class="docutils literal notranslate"><span class="pre">Discussions-To</span></code> header.</li>
</ul>
<p>The <a class="reference external" href="https://discuss.python.org/c/peps/">PEPs category</a> of the <a class="reference external" href="https://discuss.python.org/">Python Discourse</a>
is the preferred choice for most new PEPs,
whereas historically the <a class="reference external" href="https://mail.python.org/mailman3/lists/python-dev.python.org/">Python-Dev</a> mailing list was commonly used.
Some specialized topics have specific venues, such as
the <a class="reference external" href="https://discuss.python.org/c/typing/">Typing category</a> and the <a class="reference external" href="https://discuss.python.org/c/packaging/">Packaging category</a> on the Python
Discourse for typing and packaging PEPs, respectively.
If the PEP authors are unsure of the best venue,
the PEP Sponsor and PEP editors can advise them accordingly.</p>
<p>If a PEP undergoes a significant re-write or other major, substantive
changes to its proposed specification, a new thread should typically be created
in the chosen venue to solicit additional feedback. If this occurs, the
<code class="docutils literal notranslate"><span class="pre">Discussions-To</span></code> link must be updated and a new <code class="docutils literal notranslate"><span class="pre">Post-History</span></code> entry added
pointing to this new thread.</p>
<p>If it is not chosen as the discussion venue,
a brief announcement post should be made to the <a class="reference external" href="https://discuss.python.org/c/peps/">PEPs category</a>
with at least a link to the rendered PEP and the <code class="docutils literal notranslate"><span class="pre">Discussions-To</span></code> thread
when the draft PEP is committed to the repository
and if a major-enough change is made to trigger a new thread.</p>
<p>PEP authors are responsible for collecting community feedback on a PEP
before submitting it for review. However, to avoid long-winded and
open-ended discussions, strategies such as soliciting private or more
narrowly-tailored feedback in the early design phase,
collaborating with other community members with expertise in the PEPs
subject matter, and picking an appropriately-specialized discussion for the
PEPs topic (if applicable) should be considered.
PEP authors should use their discretion here.</p>
<p>Once the PEP is assigned a number and committed to the PEP repository,
substantive issues should generally be discussed on the canonical public
thread, as opposed to private channels, GitHub pull request reviews or
unrelated venues. This ensures everyone can follow and contribute,
avoids fragmenting the discussion,
and makes sure it is fully considered as part of the PEP review process.
Comments, support, concerns and other feedback on this designated thread
are a critical part of what the Steering Council or PEP-Delegate will
consider when reviewing the PEP.</p>
</section>
<section id="pep-review-resolution">
<h3><a class="toc-backref" href="#pep-review-resolution" role="doc-backlink">PEP Review &amp; Resolution</a></h3>
<p>Once the authors have completed a PEP, they may request a review for
style and consistency from the PEP editors.
However, content review and acceptance of the PEP is ultimately the
responsibility of the Steering Council, which is formally initiated by
opening a <a class="reference external" href="https://github.com/python/steering-council/issues/new/choose">Steering Council issue</a> once the authors (and sponsor, if any)
determine the PEP is ready for final review and resolution.</p>
<p>To expedite the process in selected cases (e.g. when a change is clearly
beneficial and ready to be accepted, but the PEP hasnt been formally submitted
for review yet), the Steering Council may also initiate a PEP review, first
notifying the PEP author(s) and giving them a chance to make revisions.</p>
<p>The final authority for PEP approval is the Steering Council. However, whenever
a new PEP is put forward, any core developer who believes they are suitably
experienced to make the final decision on that PEP may offer to serve as its
PEP-Delegate by <a class="reference external" href="https://github.com/python/steering-council/issues/new/choose">notifying the Steering Council</a>
of their intent. If the Steering Council approves their offer,
the PEP-Delegate will then have the authority to approve or reject that PEP.
For PEPs related to the Python type system, the Typing Council (<a class="pep reference internal" href="../pep-0729/" title="PEP 729 Typing governance process">PEP 729</a>)
provides a recommendation to the Steering Council. To request such a
recommendation, open an issue on the <a class="reference external" href="https://github.com/python/typing-council/issues">Typing Council issue tracker</a>.</p>
<p>The term “PEP-Delegate” is used under the Steering Council governance model
for the PEPs designated decision maker,
who is recorded in the “PEP-Delegate” field in the PEPs header.
The term “BDFL-Delegate” is a deprecated alias for PEP-Delegate, a legacy of
the time when when Python was led by <a class="reference internal" href="#python-s-bdfl">a BDFL</a>.
Any legacy references to “BDFL-Delegate” should be treated as equivalent to
“PEP-Delegate”.</p>
<p>An individual offering to nominate themselves as a PEP-Delegate must notify
the relevant authors and (when present) the sponsor for the PEP, and submit
their request to the Steering Council
(which can be done via a <a class="reference external" href="https://github.com/python/steering-council/issues/new/choose">new issue</a> ).
Those taking on this responsibility are free to seek
additional guidance from the Steering Council at any time, and are also expected
to take the advice and perspectives of other core developers into account.</p>
<p>The Steering Council will generally approve such self-nominations by default,
but may choose to decline them.
Possible reasons for the Steering Council declining a
self-nomination as PEP-Delegate include, but are not limited to, perceptions of
a potential conflict of interest (e.g. working for the same organisation as the
PEP submitter), or simply considering another potential PEP-Delegate to be
more appropriate. If core developers (or other community members) have concerns
regarding the suitability of a PEP-Delegate for any given PEP, they may ask
the Steering Council to review the delegation.</p>
<p>If no volunteer steps forward, then the Steering Council will approach core
developers (and potentially other Python community members) with relevant
expertise, in an attempt to identify a candidate that is willing to serve as
PEP-Delegate for that PEP. If no suitable candidate can be found, then the
PEP will be marked as Deferred until one is available.</p>
<p>Previously appointed PEP-Delegates may choose to step down, or be asked to step
down by the Council, in which case a new PEP-Delegate will be appointed in the
same manner as for a new PEP (including deferral of the PEP if no suitable
replacement can be found). In the event that a PEP-Delegate is asked to step
down, this will overrule any prior acceptance or rejection of the PEP, and it
will revert to Draft status.</p>
<p>When such standing delegations are put in place, the Steering Council will
maintain sufficient public records to allow subsequent Councils, the core
developers, and the wider Python community to understand the delegations that
currently exist, why they were put in place, and the circumstances under which
they may no longer be needed.</p>
<p>For a PEP to be accepted it must meet certain minimum criteria. It
must be a clear and complete description of the proposed enhancement.
The enhancement must represent a net improvement. The proposed
implementation, if applicable, must be solid and must not complicate
the interpreter unduly. Finally, a proposed enhancement must be
“pythonic” in order to be accepted by the Steering Council. (However,
“pythonic” is an imprecise term; it may be defined as whatever is acceptable to
the Steering Council. This logic is intentionally circular.) See <a class="pep reference internal" href="../pep-0002/" title="PEP 2 Procedure for Adding New Modules">PEP 2</a>
for standard library module acceptance criteria.</p>
<p>Except where otherwise approved by the Steering Council,
pronouncements of PEP resolution will be posted to the
<a class="reference external" href="https://discuss.python.org/c/peps/">PEPs category</a> on the <a class="reference external" href="https://discuss.python.org/">Python Discourse</a>.</p>
<p>Once a PEP has been accepted, the reference implementation must be
completed. When the reference implementation is complete and incorporated
into the main source code repository, the status will be changed to “Final”.</p>
<p>To allow gathering of additional design and interface feedback before committing
to long term stability for a language feature or standard library API, a PEP
may also be marked as “Provisional”. This is short for “Provisionally Accepted”,
and indicates that the proposal has been accepted for inclusion in the reference
implementation, but additional user feedback is needed before the full design
can be considered “Final”. Unlike regular accepted PEPs, provisionally accepted
PEPs may still be Rejected or Withdrawn <em>even after the related changes have
been included in a Python release</em>.</p>
<p>Wherever possible, it is considered preferable to reduce the scope of a proposal
to avoid the need to rely on the “Provisional” status (e.g. by deferring some
features to later PEPs), as this status can lead to version compatibility
challenges in the wider Python ecosystem. <a class="pep reference internal" href="../pep-0411/" title="PEP 411 Provisional packages in the Python standard library">PEP 411</a> provides additional details
on potential use cases for the Provisional status.</p>
<p>A PEP can also be assigned the status “Deferred”. The PEP author or an
editor can assign the PEP this status when no progress is being made
on the PEP. Once a PEP is deferred, a PEP editor can reassign it
to draft status.</p>
<p>A PEP can also be “Rejected”. Perhaps after all is said and done it
was not a good idea. It is still important to have a record of this
fact. The “Withdrawn” status is similar - it means that the PEP author
themselves has decided that the PEP is actually a bad idea, or has
accepted that a competing proposal is a better alternative.</p>
<p>When a PEP is Accepted, Rejected or Withdrawn, the PEP should be updated
accordingly. In addition to updating the Status field, at the very least
the Resolution header should be added with a direct link
to the relevant post making a decision on the PEP.</p>
<p>PEPs can also be superseded by a different PEP, rendering the original
obsolete. This is intended for Informational PEPs, where version 2 of
an API can replace version 1.</p>
<p>The possible paths of the status of PEPs are as follows:</p>
<img alt="PEP process flow diagram" class="invert-in-dark-mode" src="../_images/process_flow.svg" />
<p>While not shown in the diagram, “Accepted” PEPs may technically move to
“Rejected” or “Withdrawn” even after acceptance. This will only occur if
the implementation process reveals fundamental flaws in the design that were
not noticed prior to acceptance of the PEP. Unlike Provisional PEPs, these
transitions are only permitted if the accepted proposal has <em>not</em> been included
in a Python release - released changes must instead go through the regular
deprecation process (which may require a new PEP providing the rationale for
the deprecation).</p>
<p>Some Informational and Process PEPs may also have a status of “Active”
if they are never meant to be completed. E.g. <a class="pep reference internal" href="../pep-0001/" title="PEP 1 PEP Purpose and Guidelines">PEP 1</a> (this PEP).</p>
</section>
<section id="pep-maintenance">
<h3><a class="toc-backref" href="#pep-maintenance" role="doc-backlink">PEP Maintenance</a></h3>
<p>In general, PEPs are no longer substantially modified after they have reached
the Accepted, Final, Rejected or Superseded state. Once resolution is reached,
a PEP is considered a historical document rather than a living specification.
Formal documentation of the expected behavior should be maintained elsewhere,
such as the <a class="reference external" href="https://docs.python.org/3/reference/index.html">Language Reference</a> for core features, the <a class="reference external" href="https://docs.python.org/3/library/index.html">Library Reference</a>
for standard library modules or the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/">PyPA Specifications</a> for packaging.</p>
<p>If changes based on implementation experience and user feedback are made to
Standards track PEPs while in the Provisional or (with SC approval) Accepted
state, they should be noted in the PEP, such that the PEP accurately describes
the implementation at the point where it is marked Final.</p>
<p>Active (Informational and Process) PEPs may be updated over time to reflect
changes to development practices and other details. The precise process
followed in these cases will depend on the nature and purpose of the PEP
in question.</p>
<p>Occasionally, a Deferred or even a Withdrawn PEP may be resurrected
with major updates, but it is often better to just propose a new one.</p>
</section>
</section>
<section id="what-belongs-in-a-successful-pep">
<h2><a class="toc-backref" href="#what-belongs-in-a-successful-pep" role="doc-backlink">What belongs in a successful PEP?</a></h2>
<p>Each PEP should have the following parts/sections:</p>
<ol class="arabic">
<li>Preamble <span class="target" id="index-0"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2822.html"><strong>RFC 2822</strong></a> style headers containing meta-data about the
PEP, including the PEP number, a short descriptive title (limited
to a maximum of 44 characters), the names, and optionally the
contact info for each author, etc.</li>
<li>Abstract a short (~200 word) description of the technical issue
being addressed.</li>
<li>Motivation The motivation is critical for PEPs that want to
change the Python language, library, or ecosystem. It should
clearly explain why the existing language specification is
inadequate to address the problem that the PEP solves. This can
include collecting documented support for the PEP from important
projects in the Python ecosystem. PEP submissions without
sufficient motivation may be rejected.</li>
<li>Rationale The rationale fleshes out the specification by
describing why particular design decisions were made. It should
describe alternate designs that were considered and related work,
e.g. how the feature is supported in other languages.<p>The rationale should provide evidence of consensus within the
community and discuss important objections or concerns raised
during discussion.</p>
</li>
<li>Specification The technical specification should describe the
syntax and semantics of any new language feature. The
specification should be detailed enough to allow competing,
interoperable implementations for at least the current major Python
platforms (CPython, Jython, IronPython, PyPy).</li>
<li>Backwards Compatibility All PEPs that introduce backwards
incompatibilities must include a section describing these
incompatibilities and their severity. The PEP must explain how the
author proposes to deal with these incompatibilities. PEP
submissions without a sufficient backwards compatibility treatise
may be rejected outright.</li>
<li>Security Implications If there are security concerns in relation
to the PEP, those concerns should be explicitly written out to make
sure reviewers of the PEP are aware of them.</li>
<li>How to Teach This For a PEP that adds new functionality or changes
language behavior, it is helpful to include a section on how to
teach users, new and experienced, how to apply the PEP to their
work.<p>This section may include key points and recommended documentation
changes that would help users adopt a new feature or migrate their
code to use a language change.</p>
</li>
<li>Reference Implementation The reference implementation must be
completed before any PEP is given status “Final”, but it need not
be completed before the PEP is accepted. While there is merit
to the approach of reaching consensus on the specification and
rationale before writing code, the principle of “rough consensus
and running code” is still useful when it comes to resolving many
discussions of API details.<p>The final implementation must include test code and documentation
appropriate for either the Python language reference or the
standard library reference.</p>
</li>
<li>Rejected Ideas Throughout the discussion of a PEP, various ideas
will be proposed which are not accepted. Those rejected ideas should
be recorded along with the reasoning as to why they were rejected.
This both helps record the thought process behind the final version
of the PEP as well as preventing people from bringing up the same
rejected idea again in subsequent discussions.<p>In a way this section can be thought of as a breakout section of the
Rationale section that is focused specifically on why certain ideas
were not ultimately pursued.</p>
</li>
<li>Open Issues While a PEP is in draft, ideas can come up which
warrant further discussion. Those ideas should be recorded so people
know that they are being thought about but do not have a concrete
resolution. This helps make sure all issues required for the PEP to be
ready for consideration are complete and reduces people duplicating
prior discussion.</li>
<li>Footnotes A collection of footnotes cited in the PEP, and
a place to list non-inline hyperlink targets.</li>
<li>Copyright/license Each new PEP must be placed under a dual license of
public domain and <a class="reference external" href="https://choosealicense.com/licenses/cc0-1.0/">CC0-1.0-Universal</a> (see this PEP for an example).</li>
</ol>
</section>
<section id="pep-formats-and-templates">
<h2><a class="toc-backref" href="#pep-formats-and-templates" role="doc-backlink">PEP Formats and Templates</a></h2>
<p>PEPs are UTF-8 encoded text files using the <a class="reference external" href="https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html">reStructuredText</a> format.
reStructuredText allows for rich markup that is still quite easy to
read, but also results in good-looking and functional HTML. <a class="pep reference internal" href="../pep-0012/" title="PEP 12 Sample reStructuredText PEP Template">PEP 12</a>
contains instructions and a <a class="pep reference internal" href="../pep-0012/#suggested-sections" title="PEP 12 Sample reStructuredText PEP Template § Suggested Sections">PEP template</a>.</p>
<p>The PEP text files are automatically
<a class="reference external" href="https://peps.python.org/docs/rendering_system/">converted to HTML</a>
(via a <a class="reference external" href="https://www.sphinx-doc.org/">Sphinx</a>-based <a class="pep reference internal" href="../pep-0676/" title="PEP 676 PEP Infrastructure Process">build system</a>)
for easier <a class="reference external" href="https://peps.python.org/">online reading</a>.</p>
</section>
<section id="pep-header-preamble">
<h2><a class="toc-backref" href="#pep-header-preamble" role="doc-backlink">PEP Header Preamble</a></h2>
<p>Each PEP must begin with an <span class="target" id="index-1"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2822.html"><strong>RFC 2822</strong></a> style header preamble. The headers
must appear in the following order. Headers marked with “*” are
optional and are described below. All other headers are required.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span> PEP: &lt;pep number&gt;
Title: &lt;pep title&gt;
Author: &lt;list of authors&#39; real names and optionally, email addrs&gt;
* Sponsor: &lt;real name of sponsor&gt;
* PEP-Delegate: &lt;PEP delegate&#39;s real name&gt;
Discussions-To: &lt;URL of current canonical discussion thread&gt;
Status: &lt;Draft | Active | Accepted | Provisional | Deferred | Rejected |
Withdrawn | Final | Superseded&gt;
Type: &lt;Standards Track | Informational | Process&gt;
* Topic: &lt;Governance | Packaging | Release | Typing&gt;
* Requires: &lt;pep numbers&gt;
Created: &lt;date created on, in dd-mmm-yyyy format&gt;
* Python-Version: &lt;version number&gt;
Post-History: &lt;dates, in dd-mmm-yyyy format,
inline-linked to PEP discussion threads&gt;
* Replaces: &lt;pep number&gt;
* Superseded-By: &lt;pep number&gt;
* Resolution: &lt;url&gt;
</pre></div>
</div>
<p>The Author header lists the names, and optionally the email addresses
of all the authors/owners of the PEP. The format of the Author header
values must be:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>Random J. User &lt;random@example.com&gt;
</pre></div>
</div>
<p>if the email address is included, and just:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>Random J. User
</pre></div>
</div>
<p>if the address is not given.</p>
<p>If there are multiple authors, each should be on a separate line
following <span class="target" id="index-2"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2822.html"><strong>RFC 2822</strong></a> continuation line conventions. Note that personal
email addresses in PEPs will be obscured as a defense against spam
harvesters.</p>
<p>The Sponsor field records which developer (core, or otherwise approved by the
Steering Council) is sponsoring the PEP. If one of the authors of the PEP is a
core developer then no sponsor is necessary and thus this field should be left
out.</p>
<p>The PEP-Delegate field is used to record the individual appointed by the
Steering Council to make the final decision on whether or not to approve or
reject a PEP.</p>
<p><em>Note: The Resolution header is required for Standards Track PEPs
only. It contains a URL that should point to an email message or
other web resource where the pronouncement about
(i.e. approval or rejection of) the PEP is made.</em></p>
<p>The Discussions-To header provides the URL to the current
canonical discussion thread for the PEP.
For email lists, this should be a direct link to the thread in the lists
archives, rather than just a mailto: or hyperlink to the list itself.</p>
<p>The Type header specifies the type of PEP: Standards Track,
Informational, or Process.</p>
<p>The optional Topic header lists the special topic, if any,
the PEP belongs under.
See the <a class="reference internal" href="../topic/#topic-index"><span class="std std-ref">Topic Index</span></a> for the existing topics.</p>
<p>The Created header records the date that the PEP was assigned a
number, while Post-History is used to record the dates of and corresponding
URLs to the Discussions-To threads for the PEP, with the former as the
linked text, and the latter as the link target.
Both sets of dates should be in <code class="docutils literal notranslate"><span class="pre">dd-mmm-yyyy</span></code> format, e.g. <code class="docutils literal notranslate"><span class="pre">14-Aug-2001</span></code>.</p>
<p>Standards Track PEPs will typically have a Python-Version header which
indicates the version of Python that the feature will be released with.
Standards Track PEPs without a Python-Version header indicate
interoperability standards that will initially be supported through
external libraries and tools, and then potentially supplemented by a later PEP
to add support to the standard library. Informational and Process PEPs do
not need a Python-Version header.</p>
<p>PEPs may have a Requires header, indicating the PEP numbers that this
PEP depends on.</p>
<p>PEPs may also have a Superseded-By header indicating that a PEP has
been rendered obsolete by a later document; the value is the number of
the PEP that replaces the current document. The newer PEP must have a
Replaces header containing the number of the PEP that it rendered
obsolete.</p>
</section>
<section id="auxiliary-files">
<h2><a class="toc-backref" href="#auxiliary-files" role="doc-backlink">Auxiliary Files</a></h2>
<p>PEPs may include auxiliary files such as diagrams. Such files should be
named <code class="docutils literal notranslate"><span class="pre">pep-XXXX-Y.ext</span></code>, where “XXXX” is the PEP number, “Y” is a
serial number (starting at 1), and “ext” is replaced by the actual
file extension (e.g. “png”).</p>
<p>Alternatively, all support files may be placed in a subdirectory called
<code class="docutils literal notranslate"><span class="pre">pep-XXXX</span></code>, where “XXXX” is the PEP number. When using a subdirectory, there
are no constraints on the names used in files.</p>
</section>
<section id="changing-existing-peps">
<h2><a class="toc-backref" href="#changing-existing-peps" role="doc-backlink">Changing Existing PEPs</a></h2>
<p>Draft PEPs are freely open for discussion and proposed modification, at the
discretion of the authors, until submitted to the Steering Council or
PEP-Delegate for review and resolution. Substantive content changes should
generally be first proposed on the PEPs discussion thread listed in its
<code class="docutils literal notranslate"><span class="pre">Discussions-To</span></code> header, while copyedits and corrections can be submitted
as a <a class="reference external" href="https://github.com/python/peps/issues">GitHub issue</a> or <a class="reference external" href="https://github.com/python/peps/pulls">GitHub pull request</a>.
PEP authors with write access to the PEP repository can update the PEPs
themselves by using <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">push</span></code> or a GitHub PR to submit their changes.
For guidance on modifying other PEPs, consult the <a class="reference internal" href="#pep-maintenance">PEP Maintenance</a> section.</p>
<p>See the <a class="reference external" href="https://github.com/python/peps/blob/main/CONTRIBUTING.rst">Contributing Guide</a> for additional details, and when in doubt,
please check first with the PEP author and/or a PEP editor.</p>
</section>
<section id="transferring-pep-ownership">
<h2><a class="toc-backref" href="#transferring-pep-ownership" role="doc-backlink">Transferring PEP Ownership</a></h2>
<p>It occasionally becomes necessary to transfer ownership of PEPs to a
new champion. In general, it is preferable to retain the original author as
a co-author of the transferred PEP, but thats really up to the
original author. A good reason to transfer ownership is because the
original author no longer has the time or interest in updating it or
following through with the PEP process, or has fallen off the face of
the net (i.e. is unreachable or not responding to email). A bad
reason to transfer ownership is because the author doesnt agree with the
direction of the PEP. One aim of the PEP process is to try to build
consensus around a PEP, but if thats not possible, an author can always
submit a competing PEP.</p>
<p>If you are interested in assuming ownership of a PEP, you can also do this via
pull request. Fork the <a class="reference external" href="https://github.com/python/peps">PEP repository</a>, make your ownership modification,
and submit a pull request. You should mention both the original author and
<code class="docutils literal notranslate"><span class="pre">&#64;python/pep-editors</span></code> in a comment on the pull request. (If the original
authors GitHub username is unknown, use email.) If the original author
doesnt respond in a timely manner, the PEP editors will make a
unilateral decision (its not like such decisions cant be reversed :).</p>
</section>
<section id="pep-editor-responsibilities-workflow">
<h2><a class="toc-backref" href="#pep-editor-responsibilities-workflow" role="doc-backlink">PEP Editor Responsibilities &amp; Workflow</a></h2>
<p>A PEP editor must be added to the <code class="docutils literal notranslate"><span class="pre">&#64;python/pep-editors</span></code> group on GitHub and
must watch the <a class="reference external" href="https://github.com/python/peps">PEP repository</a>.</p>
<p>Note that developers with write access to the <a class="reference external" href="https://github.com/python/peps">PEP repository</a> may
handle the tasks that would normally be taken care of by the PEP editors.
Alternately, even developers may request assistance from PEP editors by
mentioning <code class="docutils literal notranslate"><span class="pre">&#64;python/pep-editors</span></code> on GitHub.</p>
<p>For each new PEP that comes in an editor does the following:</p>
<ul class="simple">
<li>Make sure that the PEP is either co-authored by a core developer, has a core
developer as a sponsor, or has a sponsor specifically approved for this PEP
by the Steering Council.</li>
<li>Read the PEP to check if it is ready: sound and complete. The ideas
must make technical sense, even if they dont seem likely to be
accepted.</li>
<li>The title should accurately describe the content.</li>
<li>The file name extension is correct (i.e. <code class="docutils literal notranslate"><span class="pre">.rst</span></code>).</li>
<li>Ensure that everyone listed as a sponsor or co-author of the PEP who has write
access to the <a class="reference external" href="https://github.com/python/peps">PEP repository</a> is added to <a class="reference external" href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners">.github/CODEOWNERS</a>.</li>
<li>Skim the PEP for obvious defects in language (spelling, grammar,
sentence structure, etc.), and code style (examples should conform to
<a class="pep reference internal" href="../pep-0007/" title="PEP 7 Style Guide for C Code">PEP 7</a> &amp; <a class="pep reference internal" href="../pep-0008/" title="PEP 8 Style Guide for Python Code">PEP 8</a>). Editors may correct problems themselves, but are
not required to do so (reStructuredText syntax is checked by the repos CI).</li>
<li>If a project is portrayed as benefiting from or supporting the PEP, make sure
there is some direct indication from the project included to make the support
clear. This is to avoid a PEP accidentally portraying a project as supporting
a PEP when in fact the support is based on conjecture.</li>
</ul>
<p>If the PEP isnt ready, an editor will send it back to the author for
revision, with specific instructions. If reST formatting is a
problem, ask the author(s) to use <a class="pep reference internal" href="../pep-0012/" title="PEP 12 Sample reStructuredText PEP Template">PEP 12</a> as a template and resubmit.</p>
<p>Once the PEP is ready for the repository, a PEP editor will:</p>
<ul>
<li>Check that the author has selected a valid PEP number or assign them a
number if they have not (almost always just the next available number, but
sometimes its a special/joke number, like 666 or 3141).<p>Remember that numbers below 100 are meta-PEPs.</p>
</li>
<li>Check that the author has correctly labeled the PEPs type
(“Standards Track”, “Informational”, or “Process”), and marked its
status as “Draft”.</li>
<li>Ensure all CI build and lint checks pass without errors,
and there are no obvious issues in the rendered preview output.</li>
<li>Merge the new (or updated) PEP.</li>
<li>Inform the author of the next steps (open a discussion thread and
update the PEP with it, post an announcement, etc).</li>
</ul>
<p>Updates to existing PEPs should be submitted as a <a class="reference external" href="https://github.com/python/peps/pulls">GitHub pull request</a>.</p>
<p>Many PEPs are written and maintained by developers with write access
to the Python codebase. The PEP editors monitor the PEP repository
for changes, and correct any structure, grammar, spelling, or
markup mistakes they see.</p>
<p>PEP editors dont pass judgment on PEPs. They merely do the
administrative &amp; editorial part (which is generally a low volume task).</p>
<p>Resources:</p>
<ul class="simple">
<li><a class="reference external" href="https://peps.python.org/">Index of Python Enhancement Proposals</a></li>
<li><a class="reference external" href="https://devguide.python.org/communication/">Following Pythons Development</a></li>
<li><a class="reference external" href="https://devguide.python.org/">Python Developers Guide</a></li>
</ul>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0001.rst">https://github.com/python/peps/blob/main/peps/pep-0001.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0001.rst">2024-01-12 20:31:04 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#what-is-a-pep">What is a PEP?</a></li>
<li><a class="reference internal" href="#pep-audience">PEP Audience</a></li>
<li><a class="reference internal" href="#pep-types">PEP Types</a></li>
<li><a class="reference internal" href="#pep-workflow">PEP Workflow</a><ul>
<li><a class="reference internal" href="#python-s-steering-council">Pythons Steering Council</a></li>
<li><a class="reference internal" href="#python-s-core-developers">Pythons Core Developers</a></li>
<li><a class="reference internal" href="#python-s-bdfl">Pythons BDFL</a></li>
<li><a class="reference internal" href="#pep-editors">PEP Editors</a></li>
<li><a class="reference internal" href="#start-with-an-idea-for-python">Start with an idea for Python</a></li>
<li><a class="reference internal" href="#submitting-a-pep">Submitting a PEP</a></li>
<li><a class="reference internal" href="#discussing-a-pep">Discussing a PEP</a></li>
<li><a class="reference internal" href="#pep-review-resolution">PEP Review &amp; Resolution</a></li>
<li><a class="reference internal" href="#pep-maintenance">PEP Maintenance</a></li>
</ul>
</li>
<li><a class="reference internal" href="#what-belongs-in-a-successful-pep">What belongs in a successful PEP?</a></li>
<li><a class="reference internal" href="#pep-formats-and-templates">PEP Formats and Templates</a></li>
<li><a class="reference internal" href="#pep-header-preamble">PEP Header Preamble</a></li>
<li><a class="reference internal" href="#auxiliary-files">Auxiliary Files</a></li>
<li><a class="reference internal" href="#changing-existing-peps">Changing Existing PEPs</a></li>
<li><a class="reference internal" href="#transferring-pep-ownership">Transferring PEP Ownership</a></li>
<li><a class="reference internal" href="#pep-editor-responsibilities-workflow">PEP Editor Responsibilities &amp; Workflow</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0001.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

171
pep-0002/index.html Normal file
View File

@ -0,0 +1,171 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 2 Procedure for Adding New Modules | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0002/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 2 Procedure for Adding New Modules | peps.python.org'>
<meta property="og:description" content="The Python Standard Library contributes significantly to Pythons success. The language comes with “batteries included”, so it is easy for people to become productive with just the standard library alone. It is therefore important that the usefulness o...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0002/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="The Python Standard Library contributes significantly to Pythons success. The language comes with “batteries included”, so it is easy for people to become productive with just the standard library alone. It is therefore important that the usefulness o...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 2</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 2 Procedure for Adding New Modules</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Brett Cannon &lt;brett&#32;&#97;t&#32;python.org&gt;,
Martijn Faassen &lt;faassen&#32;&#97;t&#32;infrae.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">07-Jul-2001</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd">07-Jul-2001, 09-Mar-2002</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#acceptance-procedure">Acceptance Procedure</a></li>
<li><a class="reference internal" href="#maintenance-procedure">Maintenance Procedure</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>The Python Standard Library contributes significantly to Pythons
success. The language comes with “batteries included”, so it is easy
for people to become productive with just the standard library alone.
It is therefore important that the usefulness of the standard library
be maintained.</p>
<p>Due to the visibility and importance of the standard library, it must
be maintained thoughtfully. As such, any code within it must be
maintained by Pythons development team which leads to a perpetual
cost to each addition made. There is also added cognitive load for
users in familiarizing themselves with what is in the standard
library to be considered.</p>
<p>New functionality is commonly added to the library in the form of new
modules. This PEP will describe the procedure for the <em>addition</em> of
new modules. <a class="pep reference internal" href="../pep-0004/" title="PEP 4 Deprecation of Standard Modules">PEP 4</a> deals with procedures for deprecation of modules;
the <em>removal</em> of old and unused modules from the standard library.</p>
</section>
<section id="acceptance-procedure">
<h2><a class="toc-backref" href="#acceptance-procedure" role="doc-backlink">Acceptance Procedure</a></h2>
<p>For top-level modules/packages, a PEP is required. The procedure for
writing a PEP is covered in <a class="pep reference internal" href="../pep-0001/" title="PEP 1 PEP Purpose and Guidelines">PEP 1</a>.</p>
<p>For submodules of a preexisting package in the standard library,
additions are at the discretion of the general Python development team
and its members.</p>
<p>General guidance on what modules typically are accepted into the
standard library, the overall process, etc. are covered in the
<a class="reference external" href="https://devguide.python.org/stdlibchanges/">developers guide</a>.</p>
</section>
<section id="maintenance-procedure">
<h2><a class="toc-backref" href="#maintenance-procedure" role="doc-backlink">Maintenance Procedure</a></h2>
<p>Anything accepted into the standard library is expected to be
primarily maintained there, within Pythons development infrastructure.
While some members of the development team may choose to maintain a
backport of a module outside of the standard library, it is up to them
to keep their external code in sync as appropriate.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0002.rst">https://github.com/python/peps/blob/main/peps/pep-0002.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0002.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#acceptance-procedure">Acceptance Procedure</a></li>
<li><a class="reference internal" href="#maintenance-procedure">Maintenance Procedure</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0002.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

176
pep-0003/index.html Normal file
View File

@ -0,0 +1,176 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 3 Guidelines for Handling Bug Reports | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0003/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 3 Guidelines for Handling Bug Reports | peps.python.org'>
<meta property="og:description" content="Python Enhancement Proposals (PEPs)">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0003/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python Enhancement Proposals (PEPs)">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 3</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 3 Guidelines for Handling Bug Reports</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Jeremy Hylton &lt;jeremy&#32;&#97;t&#32;alum.mit.edu&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">25-Sep-2000</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#original-guidelines">Original Guidelines</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated withdrawn admonition important">
<p class="admonition-title">Important</p>
<p>This PEP has been withdrawn.</p>
<p class="close-button">×</p>
<p>This PEP contained guidelines for handling bug reports in the Python
bug tracker. It has been replaced by the
<a class="reference external" href="https://devguide.python.org/triage/triaging/index.html">Developers Guide description of issue triaging</a>.
Guidelines for people submitting Python bugs are <a class="reference external" href="http://docs.python.org/bugs.html">in the Python docs</a>.</p>
<p></p>
</div>
<section id="original-guidelines">
<h2><a class="toc-backref" href="#original-guidelines" role="doc-backlink">Original Guidelines</a></h2>
<ol class="arabic">
<li>Make sure the bug category and bug group are correct. If they are
correct, it is easier for someone interested in helping to find
out, say, what all the open Tkinter bugs are.</li>
<li>If its a minor feature request that you dont plan to address
right away, add it to <a class="pep reference internal" href="../pep-0042/" title="PEP 42 Feature Requests">PEP 42</a> or ask the owner to add it for you.
If you add the bug to <a class="pep reference internal" href="../pep-0042/" title="PEP 42 Feature Requests">PEP 42</a>, mark the bug as “feature request”,
“later”, and “closed”; and add a comment to the bug saying that
this is the case (mentioning the PEP explicitly).<blockquote>
<div><div class="highlight-default notranslate"><div class="highlight"><pre><span></span>XXX do we prefer the tracker or PEP 42?
</pre></div>
</div>
</div></blockquote>
</li>
<li>Assign the bug a reasonable priority. We dont yet have a clear
sense of what each priority should mean. One rule, however, is
that bugs with priority “urgent” or higher must be fixed before
the next release.</li>
<li>If a bug report doesnt have enough information to allow you to
reproduce or diagnose it, ask the original submitter for more
information. If the original report is really thin and your email
doesnt get a response after a reasonable waiting period, you can
close the bug.</li>
<li>If you fix a bug, mark the status as “Fixed” and close it. In the
comments, include the SVN revision numbers of the commit(s). In
the SVN checkin message, include the issue number <strong>and</strong> a
normal description of the change, mentioning the contributor if a
patch was applied.</li>
<li>If you are assigned a bug that you are unable to deal with, assign
it to someone else if you think they will be able to deal with it,
otherwise its probably best to unassign it.</li>
</ol>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://bugs.python.org">https://bugs.python.org</a></li>
</ul>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0003.rst">https://github.com/python/peps/blob/main/peps/pep-0003.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0003.rst">2024-04-14 20:08:31 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#original-guidelines">Original Guidelines</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0003.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

152
pep-0004/index.html Normal file
View File

@ -0,0 +1,152 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 4 Deprecation of Standard Modules | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0004/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 4 Deprecation of Standard Modules | peps.python.org'>
<meta property="og:description" content="When new modules were added to the standard Python library in the past, it was not possible to foresee whether they would still be useful in the future. Even though Python “Comes With Batteries Included”, batteries may discharge over time. Carrying ol...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0004/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="When new modules were added to the standard Python library in the past, it was not possible to foresee whether they would still be useful in the future. Even though Python “Comes With Batteries Included”, batteries may discharge over time. Carrying ol...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 4</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 4 Deprecation of Standard Modules</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Brett Cannon &lt;brett&#32;&#97;t&#32;python.org&gt;, Martin von Löwis &lt;martin&#32;&#97;t&#32;v.loewis.de&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">01-Oct-2000</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#procedure-for-declaring-a-module-deprecated">Procedure for declaring a module deprecated</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>When new modules were added to the standard Python library in the
past, it was not possible to foresee whether they would still be
useful in the future. Even though Python “Comes With Batteries
Included”, batteries may discharge over time. Carrying old modules
around is a burden on the maintainer, especially when there is no
interest in the module anymore.</p>
<p>At the same time, removing a module from the distribution is
difficult, as it is not known in general whether anybody is still
using it. This PEP defines a procedure for removing modules from the
standard Python library. Usage of a module may be deprecated, which
means that it may be removed from a future Python release.</p>
</section>
<section id="procedure-for-declaring-a-module-deprecated">
<h2><a class="toc-backref" href="#procedure-for-declaring-a-module-deprecated" role="doc-backlink">Procedure for declaring a module deprecated</a></h2>
<p>To remove a top-level module/package from the standard library, a PEP
is required. The deprecation process is outlined in <a class="pep reference internal" href="../pep-0387/" title="PEP 387 Backwards Compatibility Policy">PEP 387</a>.</p>
<p>For removing a submodule of a package in the standard library,
<a class="pep reference internal" href="../pep-0387/" title="PEP 387 Backwards Compatibility Policy">PEP 387</a> must be followed, but a PEP is not required.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0004.rst">https://github.com/python/peps/blob/main/peps/pep-0004.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0004.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#procedure-for-declaring-a-module-deprecated">Procedure for declaring a module deprecated</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0004.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

186
pep-0005/index.html Normal file
View File

@ -0,0 +1,186 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 5 Guidelines for Language Evolution | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0005/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 5 Guidelines for Language Evolution | peps.python.org'>
<meta property="og:description" content="In the natural evolution of programming languages it is sometimes necessary to make changes that modify the behavior of older programs. This PEP proposes a policy for implementing these changes in a manner respectful of the installed base of Python users.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0005/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="In the natural evolution of programming languages it is sometimes necessary to make changes that modify the behavior of older programs. This PEP proposes a policy for implementing these changes in a manner respectful of the installed base of Python users.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 5</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 5 Guidelines for Language Evolution</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Paul Prescod &lt;paul&#32;&#97;t&#32;prescod.net&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Replaced by another succeeding PEP">Superseded</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">26-Oct-2000</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
<dt class="field-even">Superseded-By<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../pep-0387/">387</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#implementation-details">Implementation Details</a></li>
<li><a class="reference internal" href="#scope">Scope</a></li>
<li><a class="reference internal" href="#steps-for-introducing-backwards-incompatible-features">Steps For Introducing Backwards-Incompatible Features</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>In the natural evolution of programming languages it is sometimes
necessary to make changes that modify the behavior of older programs.
This PEP proposes a policy for implementing these changes in a manner
respectful of the installed base of Python users.</p>
</section>
<section id="implementation-details">
<h2><a class="toc-backref" href="#implementation-details" role="doc-backlink">Implementation Details</a></h2>
<p>Implementation of this PEP requires the addition of a formal warning
and deprecation facility that will be described in another proposal.</p>
</section>
<section id="scope">
<h2><a class="toc-backref" href="#scope" role="doc-backlink">Scope</a></h2>
<p>These guidelines apply to future versions of Python that introduce
backward-incompatible behavior. Backward incompatible behavior is a
major deviation in Python interpretation from an earlier behavior
described in the standard Python documentation. Removal of a feature
also constitutes a change of behavior.</p>
<p>This PEP does not replace or preclude other compatibility strategies
such as dynamic loading of backwards-compatible parsers. On the other
hand, if execution of “old code” requires a special switch or pragma
then that is indeed a change of behavior from the point of view of the
user and that change should be implemented according to these
guidelines.</p>
<p>In general, common sense must prevail in the implementation of these
guidelines. For instance changing “sys.copyright” does not constitute
a backwards-incompatible change of behavior!</p>
</section>
<section id="steps-for-introducing-backwards-incompatible-features">
<h2><a class="toc-backref" href="#steps-for-introducing-backwards-incompatible-features" role="doc-backlink">Steps For Introducing Backwards-Incompatible Features</a></h2>
<ol class="arabic simple">
<li>Propose backwards-incompatible behavior in a PEP. The PEP must
include a section on backwards compatibility that describes in
detail a plan to complete the remainder of these steps.</li>
<li>Once the PEP is accepted as a productive direction, implement an
alternate way to accomplish the task previously provided by the
feature that is being removed or changed. For instance if the
addition operator were scheduled for removal, a new version of
Python could implement an “add()” built-in function.</li>
<li>Formally deprecate the obsolete construct in the Python
documentation.</li>
<li>Add an optional warning mode to the parser that will inform users
when the deprecated construct is used. In other words, all
programs that will behave differently in the future must trigger
warnings in this mode. Compile-time warnings are preferable to
runtime warnings. The warning messages should steer people from
the deprecated construct to the alternative construct.</li>
<li>There must be at least a one-year transition period between the
release of the transitional version of Python and the release of
the backwards incompatible version. Users will have at least a
year to test their programs and migrate them from use of the
deprecated construct to the alternative one.</li>
</ol>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0005.rst">https://github.com/python/peps/blob/main/peps/pep-0005.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0005.rst">2023-11-28 14:46:07 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#implementation-details">Implementation Details</a></li>
<li><a class="reference internal" href="#scope">Scope</a></li>
<li><a class="reference internal" href="#steps-for-introducing-backwards-incompatible-features">Steps For Introducing Backwards-Incompatible Features</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0005.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

317
pep-0006/index.html Normal file
View File

@ -0,0 +1,317 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 6 Bug Fix Releases | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0006/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 6 Bug Fix Releases | peps.python.org'>
<meta property="og:description" content="Python has historically had only a single fork of development, with releases having the combined purpose of adding new features and delivering bug fixes (these kinds of releases will be referred to as “major releases”). This PEP describes how to fork o...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0006/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python has historically had only a single fork of development, with releases having the combined purpose of adding new features and delivering bug fixes (these kinds of releases will be referred to as “major releases”). This PEP describes how to fork o...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 6</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 6 Bug Fix Releases</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Aahz &lt;aahz&#32;&#97;t&#32;pythoncraft.com&gt;, Anthony Baxter &lt;anthony&#32;&#97;t&#32;interlink.com.au&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Replaced by another succeeding PEP">Superseded</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">15-Mar-2001</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd">15-Mar-2001, 18-Apr-2001, 19-Aug-2004</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#prohibitions">Prohibitions</a></li>
<li><a class="reference internal" href="#not-quite-prohibitions">Not-Quite-Prohibitions</a></li>
<li><a class="reference internal" href="#applicability-of-prohibitions">Applicability of Prohibitions</a></li>
<li><a class="reference internal" href="#helping-the-bug-fix-releases-happen">Helping the Bug Fix Releases Happen</a></li>
<li><a class="reference internal" href="#version-numbers">Version Numbers</a></li>
<li><a class="reference internal" href="#procedure">Procedure</a></li>
<li><a class="reference internal" href="#patch-czar-history">Patch Czar History</a></li>
<li><a class="reference internal" href="#history">History</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This PEP is obsolete.
The current release policy is documented in <a class="reference external" href="https://devguide.python.org/developer-workflow/development-cycle/">the devguide</a>.
See also <a class="pep reference internal" href="../pep-0101/" title="PEP 101 Doing Python Releases 101">PEP 101</a> for mechanics of the release process.</p>
</div>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Python has historically had only a single fork of development, with
releases having the combined purpose of adding new features and
delivering bug fixes (these kinds of releases will be referred to as
“major releases”). This PEP describes how to fork off maintenance, or
bug fix, releases of old versions for the primary purpose of fixing
bugs.</p>
<p>This PEP is not, repeat NOT, a guarantee of the existence of bug fix
releases; it only specifies a procedure to be followed if bug fix
releases are desired by enough of the Python community willing to do
the work.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>With the move to SourceForge, Python development has accelerated.
There is a sentiment among part of the community that there was too
much acceleration, and many people are uncomfortable with upgrading to
new versions to get bug fixes when so many features have been added,
sometimes late in the development cycle.</p>
<p>One solution for this issue is to maintain the previous major release,
providing bug fixes until the next major release. This should make
Python more attractive for enterprise development, where Python may
need to be installed on hundreds or thousands of machines.</p>
</section>
<section id="prohibitions">
<h2><a class="toc-backref" href="#prohibitions" role="doc-backlink">Prohibitions</a></h2>
<p>Bug fix releases are required to adhere to the following restrictions:</p>
<ol class="arabic simple">
<li>There must be zero syntax changes. All <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> and <code class="docutils literal notranslate"><span class="pre">.pyo</span></code> files must
work (no regeneration needed) with all bugfix releases forked off
from a major release.</li>
<li>There must be zero pickle changes.</li>
<li>There must be no incompatible C API changes. All extensions must
continue to work without recompiling in all bugfix releases in the
same fork as a major release.</li>
</ol>
<p>Breaking any of these prohibitions requires a BDFL proclamation (and a
prominent warning in the release notes).</p>
</section>
<section id="not-quite-prohibitions">
<h2><a class="toc-backref" href="#not-quite-prohibitions" role="doc-backlink">Not-Quite-Prohibitions</a></h2>
<p>Where possible, bug fix releases should also:</p>
<ol class="arabic simple">
<li>Have no new features. The purpose of a bug fix release is to fix
bugs, not add the latest and greatest whizzo feature from the HEAD
of the CVS root.</li>
<li>Be a painless upgrade. Users should feel confident that an upgrade
from 2.x.y to 2.x.(y+1) will not break their running systems. This
means that, unless it is necessary to fix a bug, the standard
library should not change behavior, or worse yet, APIs.</li>
</ol>
</section>
<section id="applicability-of-prohibitions">
<h2><a class="toc-backref" href="#applicability-of-prohibitions" role="doc-backlink">Applicability of Prohibitions</a></h2>
<p>The above prohibitions and not-quite-prohibitions apply both for a
final release to a bugfix release (for instance, 2.4 to 2.4.1) and for
one bugfix release to the next in a series (for instance 2.4.1 to
2.4.2).</p>
<p>Following the prohibitions listed in this PEP should help keep the
community happy that a bug fix release is a painless and safe upgrade.</p>
</section>
<section id="helping-the-bug-fix-releases-happen">
<h2><a class="toc-backref" href="#helping-the-bug-fix-releases-happen" role="doc-backlink">Helping the Bug Fix Releases Happen</a></h2>
<p>Heres a few pointers on helping the bug fix release process along.</p>
<ol class="arabic simple">
<li>Backport bug fixes. If you fix a bug, and it seems appropriate,
port it to the CVS branch for the current bug fix release. If
youre unwilling or unable to backport it yourself, make a note in
the commit message, with words like Bugfix candidate or
Backport candidate.</li>
<li>If youre not sure, ask. Ask the person managing the current bug
fix releases if they think a particular fix is appropriate.</li>
<li>If theres a particular bug youd particularly like fixed in a bug
fix release, jump up and down and try to get it done. Do not wait
until 48 hours before a bug fix release is due, and then start
asking for bug fixes to be included.</li>
</ol>
</section>
<section id="version-numbers">
<h2><a class="toc-backref" href="#version-numbers" role="doc-backlink">Version Numbers</a></h2>
<p>Starting with Python 2.0, all major releases are required to have a
version number of the form X.Y; bugfix releases will always be of the
form X.Y.Z.</p>
<p>The current major release under development is referred to as release
N; the just-released major version is referred to as N-1.</p>
<p>In CVS, the bug fix releases happen on a branch. For release 2.x, the
branch is named release2x-maint. For example, the branch for the 2.3
maintenance releases is release23-maint</p>
</section>
<section id="procedure">
<h2><a class="toc-backref" href="#procedure" role="doc-backlink">Procedure</a></h2>
<p>The process for managing bugfix releases is modeled in part on the Tcl
system <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>.</p>
<p>The Patch Czar is the counterpart to the BDFL for bugfix releases.
However, the BDFL and designated appointees retain veto power over
individual patches. A Patch Czar might only be looking after a single
branch of development - its quite possible that a different person
might be maintaining the 2.3.x and the 2.4.x releases.</p>
<p>As individual patches get contributed to the current trunk of CVS,
each patch committer is requested to consider whether the patch is a
bug fix suitable for inclusion in a bugfix release. If the patch is
considered suitable, the committer can either commit the release to
the maintenance branch, or else mark the patch in the commit message.</p>
<p>In addition, anyone from the Python community is free to suggest
patches for inclusion. Patches may be submitted specifically for
bugfix releases; they should follow the guidelines in <a class="pep reference internal" href="../pep-0003/" title="PEP 3 Guidelines for Handling Bug Reports">PEP 3</a>. In
general, though, its probably better that a bug in a specific release
also be fixed on the HEAD as well as the branch.</p>
<p>The Patch Czar decides when there are a sufficient number of patches
to warrant a release. The release gets packaged up, including a
Windows installer, and made public. If any new bugs are found, they
must be fixed immediately and a new bugfix release publicized (with an
incremented version number). For the 2.3.x cycle, the Patch Czar
(Anthony) has been trying for a release approximately every six
months, but this should not be considered binding in any way on any
future releases.</p>
<p>Bug fix releases are expected to occur at an interval of roughly six
months. This is only a guideline, however - obviously, if a major bug
is found, a bugfix release may be appropriate sooner. In general, only
the N-1 release will be under active maintenance at any time. That is,
during Python 2.4s development, Python 2.3 gets bugfix releases. If,
however, someone qualified wishes to continue the work to maintain an
older release, they should be encouraged.</p>
</section>
<section id="patch-czar-history">
<h2><a class="toc-backref" href="#patch-czar-history" role="doc-backlink">Patch Czar History</a></h2>
<p>Anthony Baxter is the Patch Czar for 2.3.1 through 2.3.4.</p>
<p>Barry Warsaw is the Patch Czar for 2.2.3.</p>
<p>Guido van Rossum is the Patch Czar for 2.2.2.</p>
<p>Michael Hudson is the Patch Czar for 2.2.1.</p>
<p>Anthony Baxter is the Patch Czar for 2.1.2 and 2.1.3.</p>
<p>Thomas Wouters is the Patch Czar for 2.1.1.</p>
<p>Moshe Zadka is the Patch Czar for 2.0.1.</p>
</section>
<section id="history">
<h2><a class="toc-backref" href="#history" role="doc-backlink">History</a></h2>
<p>This PEP started life as a proposal on comp.lang.python. The original
version suggested a single patch for the N-1 release to be released
concurrently with the N release. The original version also argued for
sticking with a strict bug fix policy.</p>
<p>Following feedback from the BDFL and others, the draft PEP was written
containing an expanded bugfix release cycle that permitted any
previous major release to obtain patches and also relaxed the strict
bug fix requirement (mainly due to the example of <a class="pep reference internal" href="../pep-0235/" title="PEP 235 Import on Case-Insensitive Platforms">PEP 235</a>, which
could be argued as either a bug fix or a feature).</p>
<p>Discussion then mostly moved to python-dev, where BDFL finally issued
a proclamation basing the Python bugfix release process on Tcls,
which essentially returned to the original proposal in terms of being
only the N-1 release and only bug fixes, but allowing multiple bugfix
releases until release N is published.</p>
<p>Anthony Baxter then took this PEP and revised it, based on lessons
from the 2.3 release cycle.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://www.tcl.tk/cgi-bin/tct/tip/28.html">http://www.tcl.tk/cgi-bin/tct/tip/28.html</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0006.rst">https://github.com/python/peps/blob/main/peps/pep-0006.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0006.rst">2023-11-28 14:46:07 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#prohibitions">Prohibitions</a></li>
<li><a class="reference internal" href="#not-quite-prohibitions">Not-Quite-Prohibitions</a></li>
<li><a class="reference internal" href="#applicability-of-prohibitions">Applicability of Prohibitions</a></li>
<li><a class="reference internal" href="#helping-the-bug-fix-releases-happen">Helping the Bug Fix Releases Happen</a></li>
<li><a class="reference internal" href="#version-numbers">Version Numbers</a></li>
<li><a class="reference internal" href="#procedure">Procedure</a></li>
<li><a class="reference internal" href="#patch-czar-history">Patch Czar History</a></li>
<li><a class="reference internal" href="#history">History</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0006.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

341
pep-0007/index.html Normal file
View File

@ -0,0 +1,341 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 7 Style Guide for C Code | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0007/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 7 Style Guide for C Code | peps.python.org'>
<meta property="og:description" content="This document gives coding conventions for the C code comprising the C implementation of Python. Please see the companion informational PEP describing style guidelines for Python code.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0007/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This document gives coding conventions for the C code comprising the C implementation of Python. Please see the companion informational PEP describing style guidelines for Python code.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 7</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 7 Style Guide for C Code</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;, Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">05-Jul-2001</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#c-dialect">C dialect</a></li>
<li><a class="reference internal" href="#code-lay-out">Code lay-out</a></li>
<li><a class="reference internal" href="#naming-conventions">Naming conventions</a></li>
<li><a class="reference internal" href="#documentation-strings">Documentation Strings</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This document gives coding conventions for the C code comprising the C
implementation of Python. Please see the companion informational PEP
describing <a class="pep reference internal" href="../pep-0008/" title="PEP 8 Style Guide for Python Code">style guidelines for Python code</a>.</p>
<p>Note, rules are there to be broken. Two good reasons to break a
particular rule:</p>
<ol class="arabic simple">
<li>When applying the rule would make the code less readable, even for
someone who is used to reading code that follows the rules.</li>
<li>To be consistent with surrounding code that also breaks it (maybe
for historic reasons) although this is also an opportunity to
clean up someone elses mess (in true XP style).</li>
</ol>
</section>
<section id="c-dialect">
<h2><a class="toc-backref" href="#c-dialect" role="doc-backlink">C dialect</a></h2>
<ul class="simple">
<li>Python 3.11 and newer versions use C11 without <a class="reference external" href="https://en.wikipedia.org/wiki/C11_%28C_standard_revision%29#Optional_features">optional features</a>.
The public C API should be compatible with C++.</li>
<li>Python 3.6 to 3.10 use C89 with several select C99 features:<ul>
<li>Standard integer types in <code class="docutils literal notranslate"><span class="pre">&lt;stdint.h&gt;</span></code> and <code class="docutils literal notranslate"><span class="pre">&lt;inttypes.h&gt;</span></code>. We
require the fixed width integer types.</li>
<li><code class="docutils literal notranslate"><span class="pre">static</span> <span class="pre">inline</span></code> functions</li>
<li>designated initializers (especially nice for type declarations)</li>
<li>intermingled declarations</li>
<li>booleans</li>
<li>C++-style line comments</li>
</ul>
</li>
<li>Python versions before 3.6 used ANSI/ISO standard C (the 1989 version
of the standard). This meant (amongst many other things) that all
declarations must be at the top of a block (not necessarily at the
top of function).</li>
<li>Dont use compiler-specific extensions, such as those of GCC or MSVC
(e.g. dont write multi-line strings without trailing backslashes).</li>
<li>All function declarations and definitions must use full prototypes
(i.e. specify the types of all arguments).</li>
<li>No compiler warnings with major compilers (gcc, VC++, a few others).</li>
<li><code class="docutils literal notranslate"><span class="pre">static</span> <span class="pre">inline</span></code> functions should be preferred over macros in new
code.</li>
</ul>
</section>
<section id="code-lay-out">
<h2><a class="toc-backref" href="#code-lay-out" role="doc-backlink">Code lay-out</a></h2>
<ul>
<li>Use 4-space indents and no tabs at all.</li>
<li>No line should be longer than 79 characters. If this and the
previous rule together dont give you enough room to code, your code
is too complicated consider using subroutines.</li>
<li>No line should end in whitespace. If you think you need significant
trailing whitespace, think again somebodys editor might delete
it as a matter of routine.</li>
<li>Function definition style: function name in column 1, outermost
curly braces in column 1, blank line after local variable
declarations.<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="kt">int</span>
<span class="nf">extra_ivars</span><span class="p">(</span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">type</span><span class="p">,</span><span class="w"> </span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">base</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">t_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyType_BASICSIZE</span><span class="p">(</span><span class="n">type</span><span class="p">);</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyType_BASICSIZE</span><span class="p">(</span><span class="n">base</span><span class="p">);</span>
<span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">t_size</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="n">b_size</span><span class="p">);</span><span class="w"> </span><span class="cm">/* type smaller than base! */</span>
<span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</li>
<li>Code structure: one space between keywords like <code class="docutils literal notranslate"><span class="pre">if</span></code>, <code class="docutils literal notranslate"><span class="pre">for</span></code> and
the following left paren; no spaces inside the paren; braces are
required everywhere, even where C permits them to be omitted, but do
not add them to code you are not otherwise modifying. All new C
code requires braces. Braces should be formatted as shown:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">mro</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">...</span>
<span class="p">}</span>
<span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">...</span>
<span class="p">}</span>
</pre></div>
</div>
</li>
<li>The return statement should <em>not</em> get redundant parentheses:<div class="bad highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">return</span><span class="p">(</span><span class="n">albatross</span><span class="p">);</span><span class="w"> </span><span class="cm">/* incorrect */</span>
</pre></div>
</div>
<p>Instead:</p>
<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">return</span><span class="w"> </span><span class="n">albatross</span><span class="p">;</span><span class="w"> </span><span class="cm">/* correct */</span>
</pre></div>
</div>
</li>
<li>Function and macro call style: <code class="docutils literal notranslate"><span class="pre">foo(a,</span> <span class="pre">b,</span> <span class="pre">c)</span></code> no space before
the open paren, no spaces inside the parens, no spaces before
commas, one space after each comma.</li>
<li>Always put spaces around assignment, Boolean and comparison
operators. In expressions using a lot of operators, add spaces
around the outermost (lowest-priority) operators.</li>
<li>Breaking long lines: if you can, break after commas in the outermost
argument list. Always indent continuation lines appropriately,
e.g.:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyErr_Format</span><span class="p">(</span><span class="n">PyExc_TypeError</span><span class="p">,</span>
<span class="w"> </span><span class="s">&quot;cannot create &#39;%.100s&#39; instances&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="n">type</span><span class="o">-&gt;</span><span class="n">tp_name</span><span class="p">);</span>
</pre></div>
</div>
</li>
<li>When you break a long expression at a binary operator, braces
should be formatted as shown:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">type</span><span class="o">-&gt;</span><span class="n">tp_dictoffset</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">base</span><span class="o">-&gt;</span><span class="n">tp_dictoffset</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">type</span><span class="o">-&gt;</span><span class="n">tp_dictoffset</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">b_size</span>
<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="kt">size_t</span><span class="p">)</span><span class="n">t_size</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">b_size</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="p">))</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="cm">/* &quot;Forgive&quot; adding a __dict__ only */</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Its OK to put operators at ends of lines, especially to be
consistent with surrounding code.
(See <a class="reference internal" href="../pep-0008/#pep8-operator-linebreak"><span class="std std-ref">PEP 8</span></a> for a longer discussion.)</p>
</li>
<li>Vertically align line continuation characters in multi-line macros.</li>
<li>Macros intended to be used as a statement should use the
<code class="docutils literal notranslate"><span class="pre">do</span> <span class="pre">{</span> <span class="pre">...</span> <span class="pre">}</span> <span class="pre">while</span> <span class="pre">(0)</span></code> macro idiom,
without a final semicolon.
Example:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#define ADD_INT_MACRO(MOD, INT) \</span>
<span class="cp"> do { \</span>
<span class="cp"> if (PyModule_AddIntConstant((MOD), (#INT), (INT)) &lt; 0) { \</span>
<span class="cp"> goto error; \</span>
<span class="cp"> } \</span>
<span class="cp"> } while (0)</span>
<span class="c1">// To be used like a statement with a semicolon:</span>
<span class="n">ADD_INT_MACRO</span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="n">SOME_CONSTANT</span><span class="p">);</span>
</pre></div>
</div>
</li>
<li><code class="docutils literal notranslate"><span class="pre">#undef</span></code> file local macros after use.</li>
<li>Put blank lines around functions, structure definitions, and major
sections inside functions.</li>
<li>Comments go before the code they describe.</li>
<li>All functions and global variables should be declared static unless
they are to be part of a published interface.</li>
<li>For external functions and variables, we always have a declaration
in an appropriate header file in the “Include” directory, which uses
the <code class="docutils literal notranslate"><span class="pre">PyAPI_FUNC()</span></code> macro and <code class="docutils literal notranslate"><span class="pre">PyAPI_DATA()</span></code> macro, like this:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyAPI_FUNC</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="n">PyObject_Repr</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="p">);</span>
<span class="n">PyAPI_DATA</span><span class="p">(</span><span class="n">PyTypeObject</span><span class="p">)</span><span class="w"> </span><span class="n">PySuper_Type</span><span class="p">;</span>
</pre></div>
</div>
</li>
</ul>
</section>
<section id="naming-conventions">
<h2><a class="toc-backref" href="#naming-conventions" role="doc-backlink">Naming conventions</a></h2>
<ul class="simple">
<li>Use a <code class="docutils literal notranslate"><span class="pre">Py</span></code> prefix for public functions; never for static
functions. The <code class="docutils literal notranslate"><span class="pre">Py_</span></code> prefix is reserved for global service
routines like <code class="docutils literal notranslate"><span class="pre">Py_FatalError</span></code>; specific groups of routines
(e.g. specific object type APIs) use a longer prefix,
e.g. <code class="docutils literal notranslate"><span class="pre">PyString_</span></code> for string functions.</li>
<li>Public functions and variables use MixedCase with underscores, like
this: <code class="docutils literal notranslate"><span class="pre">PyObject_GetAttr</span></code>, <code class="docutils literal notranslate"><span class="pre">Py_BuildValue</span></code>, <code class="docutils literal notranslate"><span class="pre">PyExc_TypeError</span></code>.</li>
<li>Occasionally an “internal” function has to be visible to the loader;
we use the <code class="docutils literal notranslate"><span class="pre">_Py</span></code> prefix for this, e.g.: <code class="docutils literal notranslate"><span class="pre">_PyObject_Dump</span></code>.</li>
<li>Macros should have a MixedCase prefix and then use upper case, for
example: <code class="docutils literal notranslate"><span class="pre">PyString_AS_STRING</span></code>, <code class="docutils literal notranslate"><span class="pre">Py_PRINT_RAW</span></code>.</li>
<li>Macro parameters should use <code class="docutils literal notranslate"><span class="pre">ALL_CAPS</span></code> style,
so they are easily distinguishable from C variables and struct members.</li>
</ul>
</section>
<section id="documentation-strings">
<h2><a class="toc-backref" href="#documentation-strings" role="doc-backlink">Documentation Strings</a></h2>
<ul>
<li>Use the <code class="docutils literal notranslate"><span class="pre">PyDoc_STR()</span></code> or <code class="docutils literal notranslate"><span class="pre">PyDoc_STRVAR()</span></code> macro for docstrings
to support building Python without docstrings (<code class="docutils literal notranslate"><span class="pre">./configure</span>
<span class="pre">--without-doc-strings</span></code>).</li>
<li>The first line of each function docstring should be a “signature
line” that gives a brief synopsis of the arguments and return value.
For example:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyDoc_STRVAR</span><span class="p">(</span><span class="n">myfunction__doc__</span><span class="p">,</span>
<span class="s">&quot;myfunction(name, value) -&gt; bool</span><span class="se">\n\n</span><span class="s">\</span>
<span class="s">Determine whether name and value make a valid pair.&quot;</span><span class="p">);</span>
</pre></div>
</div>
<p>Always include a blank line between the signature line and the text
of the description.</p>
<p>If the return value for the function is always <code class="docutils literal notranslate"><span class="pre">None</span></code> (because there
is no meaningful return value), do not include the indication of the
return type.</p>
</li>
<li>When writing multi-line docstrings, be sure to always use backslash
continuations, as in the example above, or string literal
concatenation:<div class="good highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyDoc_STRVAR</span><span class="p">(</span><span class="n">myfunction__doc__</span><span class="p">,</span>
<span class="s">&quot;myfunction(name, value) -&gt; bool</span><span class="se">\n\n</span><span class="s">&quot;</span>
<span class="s">&quot;Determine whether name and value make a valid pair.&quot;</span><span class="p">);</span>
</pre></div>
</div>
<p>Though some C compilers accept string literals without either:</p>
<div class="bad highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/* BAD -- don&#39;t do this! */</span>
<span class="n">PyDoc_STRVAR</span><span class="p">(</span><span class="n">myfunction__doc__</span><span class="p">,</span>
<span class="s">&quot;myfunction(name, value) -&gt; bool</span><span class="se">\n\n</span>
<span class="n">Determine</span><span class="w"> </span><span class="n">whether</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="n">and</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="n">make</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">valid</span><span class="w"> </span><span class="n">pair</span><span class="p">.</span><span class="s">&quot;);</span>
</pre></div>
</div>
<p>not all do; the MSVC compiler is known to complain about this.</p>
</li>
</ul>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0007.rst">https://github.com/python/peps/blob/main/peps/pep-0007.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0007.rst">2024-09-09 14:02:27 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#c-dialect">C dialect</a></li>
<li><a class="reference internal" href="#code-lay-out">Code lay-out</a></li>
<li><a class="reference internal" href="#naming-conventions">Naming conventions</a></li>
<li><a class="reference internal" href="#documentation-strings">Documentation Strings</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0007.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

1517
pep-0008/index.html Normal file

File diff suppressed because it is too large Load Diff

334
pep-0009/index.html Normal file
View File

@ -0,0 +1,334 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 9 Sample Plaintext PEP Template | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0009/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 9 Sample Plaintext PEP Template | peps.python.org'>
<meta property="og:description" content="Python Enhancement Proposals (PEPs)">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0009/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python Enhancement Proposals (PEPs)">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 9</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 9 Sample Plaintext PEP Template</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">14-Aug-2001</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
<dt class="field-even">Resolution<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/thread/2YMHVPRDWGQLA5A2FKXE2JMLM2HQEEGW/">Python-Dev thread</a></dd>
</dl>
<hr class="docutils" />
<div class="pep-banner sticky-banner deprecated withdrawn admonition important">
<p class="admonition-title">Important</p>
<p>This PEP has been withdrawn.</p>
<p class="close-button">×</p>
<p>As of 05-Jan-2016, this PEP is officially deprecated and replaced
by <a class="pep reference internal" href="../pep-0012/" title="PEP 12 Sample reStructuredText PEP Template">PEP 12</a>. All PEPs should now use the reStructuredText format
described by <a class="pep reference internal" href="../pep-0012/" title="PEP 12 Sample reStructuredText PEP Template">PEP 12</a>, and plaintext PEPs will no longer be
accepted.</p>
<p></p>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Abstract
This PEP provides a boilerplate or sample template for creating
your own plaintext PEPs. In conjunction with the content
guidelines in PEP 1 [1], this should make it easy for you to
conform your own PEPs to the format outlined below.
Note: if you are reading this PEP via the web, you should first
grab the plaintext source of this PEP in order to complete the
steps below. DO NOT USE THE HTML FILE AS YOUR TEMPLATE!
To get the source this (or any) PEP, look at the top of the HTML
page and click on the date &amp; time on the &quot;Last-Modified&quot; line. It
is a link to the source text in the Python repository.
If you would prefer to use lightweight markup in your PEP, please
see PEP 12, &quot;Sample reStructuredText PEP Template&quot; [2].
Rationale
PEP submissions come in a wide variety of forms, not all adhering
to the format guidelines set forth below. Use this template, in
conjunction with the content guidelines in PEP 1, to ensure that
your PEP submission won&#39;t get automatically rejected because of
form.
How to Use This Template
To use this template you must first decide whether your PEP is
going to be an Informational or Standards Track PEP. Most PEPs
are Standards Track because they propose a new feature for the
Python language or standard library. When in doubt, read PEP 1
for details or contact the PEP editors &lt;peps@python.org&gt;.
Once you&#39;ve decided which type of PEP yours is going to be, follow
the directions below.
- Make a copy of this file (.txt file, not HTML!) and perform the
following edits.
- Replace the &quot;PEP: 9&quot; header with &quot;PEP: XXX&quot; since you don&#39;t yet
have a PEP number assignment.
- Change the Title header to the title of your PEP.
- Leave the Version and Last-Modified headers alone; we&#39;ll take
care of those when we check your PEP into Python&#39;s Subversion
repository. These headers consist of keywords (&quot;Revision&quot; and
&quot;Date&quot; enclosed in &quot;$&quot;-signs) which are automatically expanded
by the repository. Please do not edit the expanded date or
revision text.
- Change the Author header to include your name, and optionally
your email address. Be sure to follow the format carefully:
your name must appear first, and it must not be contained in
parentheses. Your email address may appear second (or it can be
omitted) and if it appears, it must appear in angle brackets.
It is okay to obfuscate your email address.
- If there is a mailing list for discussion of your new feature,
add a Discussions-To header right after the Author header. You
should not add a Discussions-To header if the mailing list to be
used is either python-list@python.org or python-dev@python.org,
or if discussions should be sent to you directly. Most
Informational PEPs don&#39;t have a Discussions-To header.
- Change the Status header to &quot;Draft&quot;.
- For Standards Track PEPs, change the Type header to &quot;Standards
Track&quot;.
- For Informational PEPs, change the Type header to
&quot;Informational&quot;.
- For Standards Track PEPs, if your feature depends on the
acceptance of some other currently in-development PEP, add a
Requires header right after the Type header. The value should
be the PEP number of the PEP yours depends on. Don&#39;t add this
header if your dependent feature is described in a Final PEP.
- Change the Created header to today&#39;s date. Be sure to follow
the format carefully: it must be in dd-mmm-yyyy format, where
the mmm is the 3 English letter month abbreviation, e.g. one of
Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec.
- For Standards Track PEPs, after the Created header, add a
Python-Version header and set the value to the next planned
version of Python, i.e. the one your new feature will hopefully
make its first appearance in. Do not use an alpha or beta
release designation here. Thus, if the last version of Python
was 2.2 alpha 1 and you&#39;re hoping to get your new feature into
Python 2.2, set the header to:
Python-Version: 2.2
- Leave Post-History alone for now; you&#39;ll add dates to this
header each time you post your PEP to python-list@python.org or
python-dev@python.org. E.g. if you posted your PEP to the lists
on August 14, 2001 and September 3, 2001, the Post-History
header would look like:
Post-History: 14-Aug-2001, 03-Sept-2001
You must manually add new dates and check them in. If you don&#39;t
have check-in privileges, send your changes to the PEP editor.
- Add a Replaces header if your PEP obsoletes an earlier PEP. The
value of this header is the number of the PEP that your new PEP
is replacing. Only add this header if the older PEP is in
&quot;final&quot; form, i.e. is either Accepted, Final, or Rejected. You
aren&#39;t replacing an older open PEP if you&#39;re submitting a
competing idea.
- Now write your Abstract, Rationale, and other content for your
PEP, replacing all this gobbledygook with your own text. Be sure
to adhere to the format guidelines below, specifically on the
prohibition of tab characters and the indentation requirements.
- Update your References and Copyright section. Usually you&#39;ll
place your PEP into the public domain, in which case just leave
the &quot;Copyright&quot; section alone. Alternatively, you can use the
Open Publication License[3], but public domain is still strongly
preferred.
- Leave the little Emacs turd at the end of this file alone,
including the formfeed character (&quot;^L&quot;, or \f).
- Send your PEP submission to the PEP editors (peps@python.org),
along with $100k in unmarked pennies. (Just kidding, I wanted
to see if you were still awake. :)
Plaintext PEP Formatting Requirements
PEP headings must begin in column zero and the initial letter of
each word must be capitalized as in book titles. Acronyms should
be in all capitals. The body of each section must be indented 4
spaces. Code samples inside body sections should be indented a
further 4 spaces, and other indentation can be used as required to
make the text readable. You must use two blank lines between the
last line of a section&#39;s body and the next section heading.
You must adhere to the Emacs convention of adding two spaces at
the end of every sentence. You should fill your paragraphs to
column 70, but under no circumstances should your lines extend
past column 79. If your code samples spill over column 79, you
should rewrite them.
Tab characters must never appear in the document at all. A PEP
should include the standard Emacs stanza included by example at
the bottom of this PEP.
When referencing an external web page in the body of a PEP, you
should include the title of the page in the text, with a
footnote reference to the URL. Do not include the URL in the body
text of the PEP. E.g.
Refer to the Python Language web site [1] for more details.
...
[1] http://www.python.org
When referring to another PEP, include the PEP number in the body
text, such as &quot;PEP 1&quot;. The title may optionally appear. Add a
footnote reference, a number in square brackets. The footnote
body should include the PEP&#39;s title and author. It may optionally
include the explicit URL on a separate line, but only in the
References section. Note that the pep2html.py script will
calculate URLs automatically. For example:
...
Refer to PEP 1 [7] for more information about PEP style
...
References
[7] PEP 1, PEP Purpose and Guidelines, Warsaw, Hylton
http://peps.python.org/pep-0001/
If you decide to provide an explicit URL for a PEP, please use
this as the URL template:
http://peps.python.org/pep-xxxx/
PEP numbers in URLs must be padded with zeros from the left, so as
to be exactly 4 characters wide, however PEP numbers in the text
are never padded.
References
[1] PEP 1, PEP Purpose and Guidelines, Warsaw, Hylton
http://peps.python.org/pep-0001/
[2] PEP 12, Sample reStructuredText PEP Template, Goodger, Warsaw
http://peps.python.org/pep-0012/
[3] http://www.opencontent.org/openpub/
Copyright
This document has been placed in the public domain.
</pre></div>
</div>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0009.rst">https://github.com/python/peps/blob/main/peps/pep-0009.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0009.rst">2024-04-14 20:08:31 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0009.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

184
pep-0010/index.html Normal file
View File

@ -0,0 +1,184 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 10 Voting Guidelines | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0010/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 10 Voting Guidelines | peps.python.org'>
<meta property="og:description" content="This PEP outlines the python-dev voting guidelines. These guidelines serve to provide feedback or gauge the “wind direction” on a particular proposal, idea, or feature. They dont have a binding force.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0010/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP outlines the python-dev voting guidelines. These guidelines serve to provide feedback or gauge the “wind direction” on a particular proposal, idea, or feature. They dont have a binding force.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 10</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 10 Voting Guidelines</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">07-Mar-2002</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd">07-Mar-2002</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#voting-scores">Voting Scores</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP outlines the python-dev voting guidelines. These guidelines
serve to provide feedback or gauge the “wind direction” on a
particular proposal, idea, or feature. They dont have a binding
force.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>When a new idea, feature, patch, etc. is floated in the Python
community, either through a PEP or on the mailing lists (most likely
on python-dev <a class="footnote-reference brackets" href="#id3" id="id1">[1]</a>), it is sometimes helpful to gauge the communitys
general sentiment. Sometimes people just want to register their
opinion of an idea. Sometimes the BDFL wants to take a straw poll.
Whatever the reason, these guidelines have been adopted so as to
provide a common language for developers.</p>
<p>While opinions are (sometimes) useful, but they are never binding.
Opinions that are accompanied by rationales are always valued higher
than bare scores (this is especially true with -1 votes).</p>
</section>
<section id="voting-scores">
<h2><a class="toc-backref" href="#voting-scores" role="doc-backlink">Voting Scores</a></h2>
<p>The scoring guidelines are loosely derived from the Apache voting
procedure <a class="footnote-reference brackets" href="#id4" id="id2">[2]</a>, with of course our own spin on things. There are 4
possible vote scores:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">+1</span></code> I like it</li>
<li><code class="docutils literal notranslate"><span class="pre">+0</span></code> I dont care, but go ahead</li>
<li><code class="docutils literal notranslate"><span class="pre">-0</span></code> I dont care, so why bother?</li>
<li><code class="docutils literal notranslate"><span class="pre">-1</span></code> I hate it</li>
</ul>
<p>You may occasionally see wild flashes of enthusiasm (either for or
against) with vote scores like +2, +1000, or -1000. These arent
really valued much beyond the above scores, but its nice to see
people get excited about such geeky stuff.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id3" role="doc-footnote">
<dt class="label" id="id3">[<a href="#id1">1</a>]</dt>
<dd>Python Developers Guide,
(<a class="reference external" href="http://www.python.org/dev/">http://www.python.org/dev/</a>)</aside>
<aside class="footnote brackets" id="id4" role="doc-footnote">
<dt class="label" id="id4">[<a href="#id2">2</a>]</dt>
<dd>Apache Project Guidelines and Voting Rules
(<a class="reference external" href="http://httpd.apache.org/dev/guidelines.html">http://httpd.apache.org/dev/guidelines.html</a>)</aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0010.rst">https://github.com/python/peps/blob/main/peps/pep-0010.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0010.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#voting-scores">Voting Scores</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0010.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

624
pep-0011/index.html Normal file
View File

@ -0,0 +1,624 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 11 CPython platform support | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0011/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 11 CPython platform support | peps.python.org'>
<meta property="og:description" content="This PEP documents how an operating system (platform) becomes supported in CPython, what platforms are currently supported, and documents past support.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0011/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP documents how an operating system (platform) becomes supported in CPython, what platforms are currently supported, and documents past support.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 11</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 11 CPython platform support</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Martin von Löwis &lt;martin&#32;&#97;t&#32;v.loewis.de&gt;,
Brett Cannon &lt;brett&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">07-Jul-2002</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/thread/DSSGXU5LBCMKYMZBRVB6RF3YAB6ST5AV/" title="Python-Dev thread">18-Aug-2007</a>,
<a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/thread/T7WTUJ6TD3IGYGWV3M4PHJWNLM2WPZAW/" title="Python-Dev thread">14-May-2014</a>,
<a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/thread/OEQHRR2COYZDL6LZ42RBZOMIUB32WI34/" title="Python-Dev thread">20-Feb-2015</a>,
<a class="reference external" href="https://mail.python.org/archives/list/python-committers&#64;python.org/thread/K757345KX6W5ZLTWYBUXOXQTJJTL7GW5/" title="Python-Committers thread">10-Mar-2022</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#support-tiers">Support tiers</a><ul>
<li><a class="reference internal" href="#tier-1">Tier 1</a></li>
<li><a class="reference internal" href="#tier-2">Tier 2</a></li>
<li><a class="reference internal" href="#tier-3">Tier 3</a></li>
<li><a class="reference internal" href="#all-other-platforms">All other platforms</a></li>
<li><a class="reference internal" href="#notes">Notes</a><ul>
<li><a class="reference internal" href="#microsoft-windows">Microsoft Windows</a></li>
<li><a class="reference internal" href="#legacy-c-locale">Legacy C Locale</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#unsupporting-platforms">Unsupporting platforms</a></li>
<li><a class="reference internal" href="#no-longer-supported-platforms">No-longer-supported platforms</a></li>
<li><a class="reference internal" href="#discussions">Discussions</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP documents how an operating system (platform) becomes
supported in CPython, what platforms are currently supported, and
documents past support.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>Over time, the CPython source code has collected various pieces of
platform-specific code, which, at some point in time, was
considered necessary to use CPython on a specific platform.
Without access to this platform, it is not possible to determine
whether this code is still needed. As a result, this code may
either break during CPythons evolution, or it may become
unnecessary as the platforms evolve as well.</p>
<p>Allowing these fragments to grow poses the risk of
unmaintainability: without having experts for a large number of
platforms, it is not possible to determine whether a certain
change to the CPython source code will work on all supported
platforms.</p>
<p>To reduce this risk, this PEP specifies what is required for a
platform to be considered supported by CPython as well as providing a
procedure to remove code for platforms with few or no CPython
users.</p>
<p>This PEP also lists what platforms <em>are</em> supported by the CPython
interpreter. This lets people know what platforms are directly
supported by the CPython development team.</p>
</section>
<section id="support-tiers">
<h2><a class="toc-backref" href="#support-tiers" role="doc-backlink">Support tiers</a></h2>
<p>Platform support is broken down into <em>tiers</em>. Each tier comes with
different requirements which lead to different promises being made
about support.</p>
<p>To be promoted to a tier, steering council support is required and is
expected to be driven by team consensus. Demotion to a lower tier
occurs when the requirements of the current tier are no longer met for
a platform for an extended period of time based on the judgment of
the release manager or steering council. For platforms which no longer
meet the requirements of any tier by b1 of a new feature release, an
announcement will be made to warn the community of the pending removal
of support for the platform (e.g. in the b1 announcement). If the
platform is not brought into line for at least one of the tiers by the
first release candidate, it will be listed as unsupported in this PEP.</p>
<section id="tier-1">
<h3><a class="toc-backref" href="#tier-1" role="doc-backlink">Tier 1</a></h3>
<ul class="simple">
<li><a class="reference external" href="https://github.com/python/cpython/actions/workflows/build.yml?query=branch%3Amain+is%3Acompleted">STATUS</a></li>
<li>CI failures block releases.</li>
<li>Changes which would break the <code class="docutils literal notranslate"><span class="pre">main</span></code> branch are not allowed to be merged;
any breakage should be fixed or reverted immediately.</li>
<li>All core developers are responsible to keep <code class="docutils literal notranslate"><span class="pre">main</span></code>, and thus these
platforms, working.</li>
<li>Failures on these platforms <strong>block a release</strong>.</li>
</ul>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Target Triple</th>
<th class="head">Notes</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>aarch64-apple-darwin</td>
<td>clang</td>
</tr>
<tr class="row-odd"><td>i686-pc-windows-msvc</td>
<td></td>
</tr>
<tr class="row-even"><td>x86_64-pc-windows-msvc</td>
<td></td>
</tr>
<tr class="row-odd"><td>x86_64-apple-darwin</td>
<td>BSD libc, clang</td>
</tr>
<tr class="row-even"><td>x86_64-unknown-linux-gnu</td>
<td>glibc, gcc</td>
</tr>
</tbody>
</table>
</section>
<section id="tier-2">
<h3><a class="toc-backref" href="#tier-2" role="doc-backlink">Tier 2</a></h3>
<ul class="simple">
<li><a class="reference external" href="https://buildbot.python.org/all/#/builders?tags=%2B3.x&amp;tags=%2Btier-2">STATUS</a></li>
<li>Must have a reliable buildbot.</li>
<li>At least <strong>two</strong> core developers are signed up to support the platform.</li>
<li>Changes which break any of these platforms are to be <strong>fixed or
reverted within 24 hours</strong>.</li>
<li>Failures on these platforms <strong>block a release</strong>.</li>
</ul>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Target Triple</th>
<th class="head">Notes</th>
<th class="head">Contacts</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>aarch64-unknown-linux-gnu</td>
<td>glibc, gcc<p>glibc, clang</p>
</td>
<td>Petr Viktorin, Victor Stinner<p>Victor Stinner, Gregory P. Smith</p>
</td>
</tr>
<tr class="row-odd"><td>wasm32-unknown-wasi</td>
<td>WASI SDK, Wasmtime</td>
<td>Brett Cannon, Eric Snow</td>
</tr>
<tr class="row-even"><td>x86_64-unknown-linux-gnu</td>
<td>glibc, clang</td>
<td>Victor Stinner, Gregory P. Smith</td>
</tr>
</tbody>
</table>
</section>
<section id="tier-3">
<h3><a class="toc-backref" href="#tier-3" role="doc-backlink">Tier 3</a></h3>
<ul class="simple">
<li><a class="reference external" href="https://buildbot.python.org/all/#/builders?tags=%2B3.x&amp;tags=%2Btier-3">STATUS</a></li>
<li>Must have a reliable buildbot.</li>
<li>At least <strong>one</strong> core developer is signed up to support the platform.</li>
<li>No response SLA to failures.</li>
<li>Failures on these platforms do <strong>not</strong> block a release.</li>
</ul>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Target Triple</th>
<th class="head">Notes</th>
<th class="head">Contacts</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>aarch64-pc-windows-msvc</td>
<td></td>
<td>Steve Dower</td>
</tr>
<tr class="row-odd"><td>arm64-apple-ios</td>
<td>iOS on device</td>
<td>Russell Keith-Magee, Ned Deily</td>
</tr>
<tr class="row-even"><td>arm64-apple-ios-simulator</td>
<td>iOS on M1 macOS simulator</td>
<td>Russell Keith-Magee, Ned Deily</td>
</tr>
<tr class="row-odd"><td>armv7l-unknown-linux-gnueabihf</td>
<td>Raspberry Pi OS, glibc, gcc</td>
<td>Gregory P. Smith</td>
</tr>
<tr class="row-even"><td>powerpc64le-unknown-linux-gnu</td>
<td>glibc, clang<p>glibc, gcc</p>
</td>
<td>Victor Stinner<p>Victor Stinner</p>
</td>
</tr>
<tr class="row-odd"><td>s390x-unknown-linux-gnu</td>
<td>glibc, gcc</td>
<td>Victor Stinner</td>
</tr>
<tr class="row-even"><td>x86_64-unknown-freebsd</td>
<td>BSD libc, clang</td>
<td>Victor Stinner</td>
</tr>
</tbody>
</table>
</section>
<section id="all-other-platforms">
<h3><a class="toc-backref" href="#all-other-platforms" role="doc-backlink">All other platforms</a></h3>
<p>Support for a platform may be partial within the code base, such as
from active development around platform support or accidentally.
Code changes to platforms not listed in the above tiers may be rejected
or removed from the code base without a deprecation process if they
cause a maintenance burden or obstruct general improvements.</p>
<p>Platforms not listed here may be supported by the wider Python
community in some way. If your desired platform is not listed above,
please perform a search online to see if someone is already providing
support in some form.</p>
</section>
<section id="notes">
<h3><a class="toc-backref" href="#notes" role="doc-backlink">Notes</a></h3>
<section id="microsoft-windows">
<h4><a class="toc-backref" href="#microsoft-windows" role="doc-backlink">Microsoft Windows</a></h4>
<p>Windows versions prior to Windows 10 follow Microsofts <a class="reference external" href="https://learn.microsoft.com/en-us/lifecycle/policies/fixed">Fixed Lifecycle Policy</a>,
with a mainstream support phase for 5 years after release,
where the product is generally commercially available,
and an additional 5 year extended support phase,
where paid support is still available and certain bug fixes are released.
<a class="reference external" href="https://learn.microsoft.com/en-us/lifecycle/faq/extended-security-updates">Extended Security Updates (ESU)</a>
is a paid program available to high-volume enterprise customers
as a “last resort” option to receive certain security updates after extended support ends.
ESU is considered a distinct phase that follows the expiration of extended support.</p>
<p>Windows 10 and later follow Microsofts <a class="reference external" href="https://learn.microsoft.com/en-us/lifecycle/policies/modern">Modern Lifecycle Policy</a>,
which varies per-product, per-version, per-edition and per-channel.
Generally, feature updates (1709, 22H2) occur every 6-12 months
and are supported for 18-36 months;
Server and IoT editions, and LTSC channel releases are supported for 5-10 years,
and the latest feature release of a major version (Windows 10, Windows 11)
generally receives new updates for at least 10 years following release.
Microsofts <a class="reference external" href="https://learn.microsoft.com/en-us/lifecycle/faq/windows">Windows Lifecycle FAQ</a>
has more specific and up-to-date guidance.</p>
<p>CPythons Windows support currently follows Microsofts lifecycles.
A new feature release X.Y.0 will support all Windows versions
whose <em>extended support</em> phase has not yet expired.
Subsequent bug fix releases will support the same Windows versions
as the original feature release, even if no longer supported by Microsoft.
New versions of Windows released while CPython is in maintenance mode
may be supported at the discretion of the core team and release manager.</p>
<p>As of 2024, our current interpretation of Microsofts lifecycles is that
Windows for IoT and embedded systems is out of scope for new CPython releases,
as the intent of those is to avoid feature updates. Windows Server will usually
be the oldest version still receiving free security fixes, and that will
determine the earliest supported client release with equivalent API version
(which will usually be past its end-of-life).</p>
<p>Each feature release is built by a specific version of Microsoft
Visual Studio. That version should have mainstream support when the
release is made. Developers of extension modules will generally need
to use the same Visual Studio release; they are concerned both with
the availability of the versions they need to use, and with keeping
the zoo of versions small. The CPython source tree will keep
unmaintained build files for older Visual Studio releases, for which
patches will be accepted. Such build files will be removed from the
source tree 3 years after the extended support for the compiler has
ended (but continue to remain available in revision control).</p>
</section>
<section id="legacy-c-locale">
<h4><a class="toc-backref" href="#legacy-c-locale" role="doc-backlink">Legacy C Locale</a></h4>
<p>Starting with CPython 3.7.0, *nix platforms are expected to provide
at least one of <code class="docutils literal notranslate"><span class="pre">C.UTF-8</span></code> (full locale), <code class="docutils literal notranslate"><span class="pre">C.utf8</span></code> (full locale) or
<code class="docutils literal notranslate"><span class="pre">UTF-8</span></code> (<code class="docutils literal notranslate"><span class="pre">LC_CTYPE</span></code>-only locale) as an alternative to the legacy <code class="docutils literal notranslate"><span class="pre">C</span></code>
locale.</p>
<p>Any Unicode-related integration problems that occur only in the legacy <code class="docutils literal notranslate"><span class="pre">C</span></code>
locale and cannot be reproduced in an appropriately configured non-ASCII
locale will be closed as “wont fix”.</p>
</section>
</section>
</section>
<section id="unsupporting-platforms">
<h2><a class="toc-backref" href="#unsupporting-platforms" role="doc-backlink">Unsupporting platforms</a></h2>
<p>If a platform drops out of tiered support, a note must be posted
in this PEP that the platform is no longer actively supported. This
note must include:</p>
<ul class="simple">
<li>The name of the system,</li>
<li>The first release number that does not support this platform
anymore, and</li>
<li>The first release where the historical support code is actively
removed.</li>
</ul>
<p>In some cases, it is not possible to identify the specific list of
systems for which some code is used (e.g. when autoconf tests for
absence of some feature which is considered present on all
supported systems). In this case, the name will give the precise
condition (usually a preprocessor symbol) that will become
unsupported.</p>
<p>At the same time, the CPython build must be changed to produce a
warning if somebody tries to install CPython on this platform. On
platforms using autoconf, configure should also be made emit a warning
about the unsupported platform.</p>
<p>This gives potential users of the platform a chance to step forward
and offer maintenance. We do not treat a platform that loses Tier 3
support any worse than a platform that was never supported.</p>
</section>
<section id="no-longer-supported-platforms">
<h2><a class="toc-backref" href="#no-longer-supported-platforms" role="doc-backlink">No-longer-supported platforms</a></h2>
<ul>
<li><div class="line-block">
<div class="line">Name: MS-DOS, MS-Windows 3.x</div>
<div class="line">Unsupported in: Python 2.0</div>
<div class="line">Code removed in: Python 2.1</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: SunOS 4</div>
<div class="line">Unsupported in: Python 2.3</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: DYNIX</div>
<div class="line">Unsupported in: Python 2.3</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: dgux</div>
<div class="line">Unsupported in: Python 2.3</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Minix</div>
<div class="line">Unsupported in: Python 2.3</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Irix 4 and with-sgi-dl</div>
<div class="line">Unsupported in: Python 2.3</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Linux 1</div>
<div class="line">Unsupported in: Python 2.3</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Systems defining __d6_pthread_create (configure.in)</div>
<div class="line">Unsupported in: Python 2.3</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Systems defining PY_PTHREAD_D4, PY_PTHREAD_D6,
or PY_PTHREAD_D7 in thread_pthread.h</div>
<div class="line">Unsupported in: Python 2.3</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Systems using with-dl-dld</div>
<div class="line">Unsupported in: Python 2.3</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Systems using without-universal-newlines,</div>
<div class="line">Unsupported in: Python 2.3</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: MacOS 9</div>
<div class="line">Unsupported in: Python 2.4</div>
<div class="line">Code removed in: Python 2.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Systems using with-wctype-functions</div>
<div class="line">Unsupported in: Python 2.6</div>
<div class="line">Code removed in: Python 2.6</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Win9x, WinME, NT4</div>
<div class="line">Unsupported in: Python 2.6 (warning in 2.5 installer)</div>
<div class="line">Code removed in: Python 2.6</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: AtheOS</div>
<div class="line">Unsupported in: Python 2.6 (with “AtheOS” changed to “Syllable”)</div>
<div class="line">Build broken in: Python 2.7 (edit configure to re-enable)</div>
<div class="line">Code removed in: Python 3.0</div>
<div class="line">Details: <a class="reference external" href="http://www.syllable.org/discussion.php?id=2320">http://www.syllable.org/discussion.php?id=2320</a></div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: BeOS</div>
<div class="line">Unsupported in: Python 2.6 (warning in configure)</div>
<div class="line">Build broken in: Python 2.7 (edit configure to re-enable)</div>
<div class="line">Code removed in: Python 3.0</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Systems using Mach C Threads</div>
<div class="line">Unsupported in: Python 3.2</div>
<div class="line">Code removed in: Python 3.3</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: SunOS lightweight processes (LWP)</div>
<div class="line">Unsupported in: Python 3.2</div>
<div class="line">Code removed in: Python 3.3</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Systems using with-pth (GNU pth threads)</div>
<div class="line">Unsupported in: Python 3.2</div>
<div class="line">Code removed in: Python 3.3</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Systems using Irix threads</div>
<div class="line">Unsupported in: Python 3.2</div>
<div class="line">Code removed in: Python 3.3</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: OSF* systems (issue 8606)</div>
<div class="line">Unsupported in: Python 3.2</div>
<div class="line">Code removed in: Python 3.3</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: OS/2 (issue 16135)</div>
<div class="line">Unsupported in: Python 3.3</div>
<div class="line">Code removed in: Python 3.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: VMS (issue 16136)</div>
<div class="line">Unsupported in: Python 3.3</div>
<div class="line">Code removed in: Python 3.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Windows 2000</div>
<div class="line">Unsupported in: Python 3.3</div>
<div class="line">Code removed in: Python 3.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Windows systems where COMSPEC points to command.com</div>
<div class="line">Unsupported in: Python 3.3</div>
<div class="line">Code removed in: Python 3.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: RISC OS</div>
<div class="line">Unsupported in: Python 3.0 (some code actually removed)</div>
<div class="line">Code removed in: Python 3.4</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: IRIX</div>
<div class="line">Unsupported in: Python 3.7</div>
<div class="line">Code removed in: Python 3.7</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: Systems without multithreading support</div>
<div class="line">Unsupported in: Python 3.7</div>
<div class="line">Code removed in: Python 3.7</div>
</div>
</li>
<li><div class="line-block">
<div class="line">Name: wasm32-unknown-emscripten</div>
<div class="line">Unsupported in: Python 3.13</div>
<div class="line">Code removed in: Unknown</div>
</div>
</li>
</ul>
</section>
<section id="discussions">
<h2><a class="toc-backref" href="#discussions" role="doc-backlink">Discussions</a></h2>
<ul class="simple">
<li>April 2022: <a class="reference external" href="https://mail.python.org/archives/list/python-committers&#64;python.org/thread/V3OZPJGA5VJFYM6XYGPZIVPOIYKX6KTD/">Consider adding a Tier 3 to tiered platform support</a>
(Victor Stinner)</li>
<li>March 2022: <a class="reference external" href="https://mail.python.org/archives/list/python-committers&#64;python.org/thread/K757345KX6W5ZLTWYBUXOXQTJJTL7GW5/">Proposed tiered platform support</a>
(Brett Cannon)</li>
<li>February 2015: <a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/thread/OEQHRR2COYZDL6LZ42RBZOMIUB32WI34/">Update to PEP 11 to clarify garnering platform support</a>
(Brett Cannon)</li>
<li>May 2014: <a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/thread/T7WTUJ6TD3IGYGWV3M4PHJWNLM2WPZAW/">Where is our official policy of what platforms we do support?</a>
(Brett Cannon)</li>
<li>August 2007: <a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/thread/DSSGXU5LBCMKYMZBRVB6RF3YAB6ST5AV/">PEP 11 update - Call for port maintainers to step forward</a>
(Skip Montanaro)</li>
</ul>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0011.rst">https://github.com/python/peps/blob/main/peps/pep-0011.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0011.rst">2024-07-16 18:26:06 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#support-tiers">Support tiers</a><ul>
<li><a class="reference internal" href="#tier-1">Tier 1</a></li>
<li><a class="reference internal" href="#tier-2">Tier 2</a></li>
<li><a class="reference internal" href="#tier-3">Tier 3</a></li>
<li><a class="reference internal" href="#all-other-platforms">All other platforms</a></li>
<li><a class="reference internal" href="#notes">Notes</a><ul>
<li><a class="reference internal" href="#microsoft-windows">Microsoft Windows</a></li>
<li><a class="reference internal" href="#legacy-c-locale">Legacy C Locale</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#unsupporting-platforms">Unsupporting platforms</a></li>
<li><a class="reference internal" href="#no-longer-supported-platforms">No-longer-supported platforms</a></li>
<li><a class="reference internal" href="#discussions">Discussions</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0011.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

964
pep-0012/index.html Normal file
View File

@ -0,0 +1,964 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 12 Sample reStructuredText PEP Template | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0012/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 12 Sample reStructuredText PEP Template | peps.python.org'>
<meta property="og:description" content="This PEP provides a boilerplate or sample template for creating your own reStructuredText PEPs. In conjunction with the content guidelines in PEP 1, this should make it easy for you to conform your own PEPs to the format outlined below.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0012/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP provides a boilerplate or sample template for creating your own reStructuredText PEPs. In conjunction with the content guidelines in PEP 1, this should make it easy for you to conform your own PEPs to the format outlined below.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 12</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 12 Sample reStructuredText PEP Template</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">David Goodger &lt;goodger&#32;&#97;t&#32;python.org&gt;,
Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;,
Brett Cannon &lt;brett&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">05-Aug-2002</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/thread/KX3AS7QAY26QH3WIUAEOCCNXQ4V2TGGV/" title="Python-Dev thread">30-Aug-2002</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#how-to-use-this-template">How to Use This Template</a></li>
<li><a class="reference internal" href="#restructuredtext-pep-formatting-requirements">ReStructuredText PEP Formatting Requirements</a><ul>
<li><a class="reference internal" href="#general">General</a></li>
<li><a class="reference internal" href="#section-headings">Section Headings</a></li>
<li><a class="reference internal" href="#paragraphs">Paragraphs</a></li>
<li><a class="reference internal" href="#inline-markup">Inline Markup</a></li>
<li><a class="reference internal" href="#block-quotes">Block Quotes</a></li>
<li><a class="reference internal" href="#literal-blocks">Literal Blocks</a></li>
<li><a class="reference internal" href="#lists">Lists</a></li>
<li><a class="reference internal" href="#tables">Tables</a></li>
<li><a class="reference internal" href="#hyperlinks">Hyperlinks</a></li>
<li><a class="reference internal" href="#internal-and-pep-rfc-links">Internal and PEP/RFC Links</a></li>
<li><a class="reference internal" href="#footnotes">Footnotes</a></li>
<li><a class="reference internal" href="#images">Images</a></li>
<li><a class="reference internal" href="#comments">Comments</a></li>
<li><a class="reference internal" href="#escaping-mechanism">Escaping Mechanism</a></li>
<li><a class="reference internal" href="#intersphinx">Intersphinx</a></li>
<li><a class="reference internal" href="#canonical-documentation">Canonical Documentation</a></li>
</ul>
</li>
<li><a class="reference internal" href="#habits-to-avoid">Habits to Avoid</a></li>
<li><a class="reference internal" href="#suggested-sections">Suggested Sections</a></li>
<li><a class="reference internal" href="#resources">Resources</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>For those who have written a PEP before, there is a <a class="reference internal" href="#template">template</a>
(which is included as a file in the <a class="reference external" href="https://github.com/python/peps/">PEPs repository</a>).</p>
</div>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP provides a boilerplate or sample template for creating your
own reStructuredText PEPs. In conjunction with the content guidelines
in <a class="pep reference internal" href="../pep-0001/" title="PEP 1 PEP Purpose and Guidelines">PEP 1</a>, this should make it easy for you to conform your own
PEPs to the format outlined below.</p>
<p>Note: if you are reading this PEP via the web, you should first grab
the text (reStructuredText) source of this PEP in order to complete
the steps below. <strong>DO NOT USE THE HTML FILE AS YOUR TEMPLATE!</strong></p>
<p>The source for this (or any) PEP can be found in the
<a class="reference external" href="https://github.com/python/peps/">PEPs repository</a>,
as well as via a link at the bottom of each PEP.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>If you intend to submit a PEP, you MUST use this template, in
conjunction with the format guidelines below, to ensure that your PEP
submission wont get automatically rejected because of form.</p>
<p>ReStructuredText provides PEP authors with useful functionality and
expressivity, while maintaining easy readability in the source text.
The processed HTML form makes the functionality accessible to readers:
live hyperlinks, styled text, tables, images, and automatic tables of
contents, among other advantages.</p>
</section>
<section id="how-to-use-this-template">
<h2><a class="toc-backref" href="#how-to-use-this-template" role="doc-backlink">How to Use This Template</a></h2>
<p>To use this template you must first decide whether your PEP is going
to be an Informational or Standards Track PEP. Most PEPs are
Standards Track because they propose a new feature for the Python
language or standard library. When in doubt, read <a class="pep reference internal" href="../pep-0001/" title="PEP 1 PEP Purpose and Guidelines">PEP 1</a> for details,
or open a tracker issue on the PEPs repo to ask for assistance.</p>
<p>Once youve decided which type of PEP yours is going to be, follow the
directions below.</p>
<ul>
<li>Make a copy of this file (the <code class="docutils literal notranslate"><span class="pre">.rst</span></code> file, <strong>not</strong> the HTML!) and
perform the following edits. Name the new file <code class="file docutils literal notranslate"><span class="pre">pep-</span><em><span class="pre">NNNN</span></em><span class="pre">.rst</span></code>, using
the next available number (not used by a published or in-PR PEP).</li>
<li>Replace the “PEP: 12” header with “PEP: NNNN”,
matching the file name. Note that the file name should be padded with
zeros (eg <code class="docutils literal notranslate"><span class="pre">pep-0012.rst</span></code>), but the header should not (<code class="docutils literal notranslate"><span class="pre">PEP:</span> <span class="pre">12</span></code>).</li>
<li>Change the Title header to the title of your PEP.</li>
<li>Change the Author header to include your name, and optionally your
email address. Be sure to follow the format carefully: your name
must appear first, and it must not be contained in parentheses.
Your email address may appear second (or it can be omitted) and if
it appears, it must appear in angle brackets. It is okay to
obfuscate your email address.</li>
<li>If none of the authors are Python core developers, include a Sponsor
header with the name of the core developer sponsoring your PEP.</li>
<li>Add the direct URL of the PEPs canonical discussion thread
(on e.g. Python-Dev, Discourse, etc) under the Discussions-To header.
If the thread will be created after the PEP is submitted as an official
draft, it is okay to just list the venue name initially, but remember to
update the PEP with the URL as soon as the PEP is successfully merged
to the PEPs repository and you create the corresponding discussion thread.
See <a class="pep reference internal" href="../pep-0001/#discussing-a-pep" title="PEP 1 PEP Purpose and Guidelines § Discussing a PEP">PEP 1</a> for more details.</li>
<li>Change the Status header to “Draft”.</li>
<li>For Standards Track PEPs, change the Type header to “Standards
Track”.</li>
<li>For Informational PEPs, change the Type header to “Informational”.</li>
<li>For Standards Track PEPs, if your feature depends on the acceptance
of some other currently in-development PEP, add a Requires header
right after the Type header. The value should be the PEP number of
the PEP yours depends on. Dont add this header if your dependent
feature is described in a Final PEP.</li>
<li>Change the Created header to todays date. Be sure to follow the
format carefully: it must be in <code class="docutils literal notranslate"><span class="pre">dd-mmm-yyyy</span></code> format, where the
<code class="docutils literal notranslate"><span class="pre">mmm</span></code> is the 3 English letter month abbreviation, i.e. one of Jan,
Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec.</li>
<li>For Standards Track PEPs, after the Created header, add a
Python-Version header and set the value to the next planned version
of Python, i.e. the one your new feature will hopefully make its
first appearance in. Do not use an alpha or beta release
designation here. Thus, if the last version of Python was 2.2 alpha
1 and youre hoping to get your new feature into Python 2.2, set the
header to:<div class="highlight-email notranslate"><div class="highlight"><pre><span></span><span class="nt">Python-Version:</span><span class="w"> </span>2.2
</pre></div>
</div>
</li>
<li>Add a Topic header if the PEP belongs under one shown at the <a class="reference internal" href="../topic/#topic-index"><span class="std std-ref">Topic Index</span></a>.
Most PEPs dont.</li>
<li>Leave Post-History alone for now; youll add dates and corresponding links
to this header each time you post your PEP to the designated discussion forum
(and update the Discussions-To header with said link, as above).
For each thread, use the date (in the <code class="docutils literal notranslate"><span class="pre">dd-mmm-yyy</span></code> format) as the
linked text, and insert the URLs inline as anonymous reST <a class="reference internal" href="#hyperlinks">hyperlinks</a>,
with commas in between each posting.<p>If you posted threads for your PEP on August 14, 2001 and September 3, 2001,
the Post-History header would look like, e.g.:</p>
<div class="highlight-email notranslate"><div class="highlight"><pre><span></span><span class="nt">Post-History:</span><span class="w"> </span>`14-Aug-2001<span class="w"> </span>&lt;https://<span class="nf">www.example.com</span>/thread_1&gt;`__,
<span class="w"> </span>`03-Sept-2001<span class="w"> </span>&lt;https://<span class="nf">www.example.com</span>/thread_2&gt;`__
</pre></div>
</div>
<p>You should add the new dates/links here as soon as you post a
new discussion thread.</p>
</li>
<li>Add a Replaces header if your PEP obsoletes an earlier PEP. The
value of this header is the number of the PEP that your new PEP is
replacing. Only add this header if the older PEP is in “final”
form, i.e. is either Accepted, Final, or Rejected. You arent
replacing an older open PEP if youre submitting a competing idea.</li>
<li>Now write your Abstract, Rationale, and other content for your PEP,
replacing all this gobbledygook with your own text. Be sure to
adhere to the format guidelines below, specifically on the
prohibition of tab characters and the indentation requirements.
See “Suggested Sections” below for a template of sections to include.</li>
<li>Update your Footnotes section, listing any footnotes and
non-inline link targets referenced by the text.</li>
<li>Run <code class="docutils literal notranslate"><span class="pre">./build.py</span></code> to ensure the PEP is rendered without errors,
and check that the output in <code class="file docutils literal notranslate"><span class="pre">build/pep-</span><em><span class="pre">NNNN</span></em><span class="pre">.html</span></code> looks as you intend.</li>
<li>Create a pull request against the <a class="reference external" href="https://github.com/python/peps/">PEPs repository</a>.</li>
</ul>
<p>For reference, here are all of the possible header fields (everything
in brackets should either be replaced or have the field removed if
it has a leading <code class="docutils literal notranslate"><span class="pre">*</span></code> marking it as optional and it does not apply to
your PEP):</p>
<div class="highlight-email notranslate"><div class="highlight"><pre><span></span><span class="nt">PEP:</span><span class="w"> </span>[NNN]
<span class="nt">Title:</span><span class="w"> </span>[...]
<span class="nt">Author:</span><span class="w"> </span>[Full<span class="w"> </span>Name<span class="w"> </span>&lt;email<span class="w"> </span>at<span class="w"> </span><span class="nf">example.com</span>&gt;]
<span class="nt">Sponsor:</span><span class="w"> </span>*[Full<span class="w"> </span>Name<span class="w"> </span>&lt;email<span class="w"> </span>at<span class="w"> </span><span class="nf">example.com</span>&gt;]
<span class="nt">PEP-Delegate:</span>
<span class="nt">Discussions-To:</span><span class="w"> </span>[URL]
<span class="nt">Status:</span><span class="w"> </span>Draft
<span class="nt">Type:</span><span class="w"> </span>[Standards<span class="w"> </span>Track<span class="w"> </span>|<span class="w"> </span>Informational<span class="w"> </span>|<span class="w"> </span>Process]
<span class="nt">Topic:</span><span class="w"> </span>*[Governance<span class="w"> </span>|<span class="w"> </span>Packaging<span class="w"> </span>|<span class="w"> </span>Release<span class="w"> </span>|<span class="w"> </span>Typing]
<span class="nt">Requires:</span><span class="w"> </span>*[NNN]
<span class="nt">Created:</span><span class="w"> </span>[DD-MMM-YYYY]
<span class="nt">Python-Version:</span><span class="w"> </span>*[M.N]
<span class="nt">Post-History:</span><span class="w"> </span>[`DD-MMM-YYYY<span class="w"> </span>&lt;URL&gt;`__]
<span class="nt">Replaces:</span><span class="w"> </span>*[NNN]
<span class="nt">Superseded-By:</span><span class="w"> </span>*[NNN]
<span class="nt">Resolution:</span>
</pre></div>
</div>
</section>
<section id="restructuredtext-pep-formatting-requirements">
<h2><a class="toc-backref" href="#restructuredtext-pep-formatting-requirements" role="doc-backlink">ReStructuredText PEP Formatting Requirements</a></h2>
<p>The following is a PEP-specific summary of reStructuredText syntax.
For the sake of simplicity and brevity, much detail is omitted. For
more detail, see <a class="reference internal" href="#resources">Resources</a> below. <a class="reference internal" href="#literal-blocks">Literal blocks</a> (in which no
markup processing is done) are used for examples throughout, to
illustrate the plaintext markup.</p>
<section id="general">
<h3><a class="toc-backref" href="#general" role="doc-backlink">General</a></h3>
<p>Lines should usually not extend past column 79,
excepting URLs and similar circumstances.
Tab characters must never appear in the document at all.</p>
</section>
<section id="section-headings">
<h3><a class="toc-backref" href="#section-headings" role="doc-backlink">Section Headings</a></h3>
<p>PEP headings must begin in column zero and the initial letter of each
word must be capitalized as in book titles. Acronyms should be in all
capitals. Section titles must be adorned with an underline, a single
repeated punctuation character, which begins in column zero and must
extend at least as far as the right edge of the title text (4
characters minimum). First-level section titles are underlined with
“=” (equals signs), second-level section titles with “-” (hyphens),
and third-level section titles with “’” (single quotes or
apostrophes). For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="gh">First-Level Title</span>
<span class="gh">=================</span>
<span class="gh">Second-Level Title</span>
<span class="gh">------------------</span>
<span class="gh">Third-Level Title</span>
<span class="gh">&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;</span>
</pre></div>
</div>
<p>If there are more than three levels of sections in your PEP, you may
insert overline/underline-adorned titles for the first and second
levels as follows:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="gh">============================</span>
<span class="gh">First-Level Title (optional)</span>
<span class="gh">============================</span>
<span class="gh">-----------------------------</span>
<span class="gh">Second-Level Title (optional)</span>
<span class="gh">-----------------------------</span>
<span class="gh">Third-Level Title</span>
<span class="gh">=================</span>
<span class="gh">Fourth-Level Title</span>
<span class="gh">------------------</span>
<span class="gh">Fifth-Level Title</span>
<span class="gh">&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;</span>
</pre></div>
</div>
<p>You shouldnt have more than five levels of sections in your PEP. If
you do, you should consider rewriting it.</p>
<p>You must use two blank lines between the last line of a sections body
and the next section heading. If a subsection heading immediately
follows a section heading, a single blank line in-between is
sufficient.</p>
<p>The body of each section is not normally indented, although some
constructs do use indentation, as described below. Blank lines are
used to separate constructs.</p>
</section>
<section id="paragraphs">
<h3><a class="toc-backref" href="#paragraphs" role="doc-backlink">Paragraphs</a></h3>
<p>Paragraphs are left-aligned text blocks separated by blank lines.
Paragraphs are not indented unless they are part of an indented
construct (such as a block quote or a list item).</p>
</section>
<section id="inline-markup">
<h3><a class="toc-backref" href="#inline-markup" role="doc-backlink">Inline Markup</a></h3>
<p>Portions of text within paragraphs and other text blocks may be
styled. For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>Text may be marked as <span class="ge">*emphasized*</span> (single asterisk markup,
typically shown in italics) or <span class="gs">**strongly emphasized**</span> (double
asterisks, typically boldface). <span class="s">``Inline literals``</span> (using double
backquotes) are typically rendered in a monospaced typeface. No
further markup recognition is done within the double backquotes,
so they&#39;re safe for any kind of code snippets.
</pre></div>
</div>
</section>
<section id="block-quotes">
<h3><a class="toc-backref" href="#block-quotes" role="doc-backlink">Block Quotes</a></h3>
<p>Block quotes consist of indented body elements. For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>This is a paragraph.
This is a block quote.
A block quote may contain many paragraphs.
</pre></div>
</div>
<p>Block quotes are used to quote extended passages from other sources.
Block quotes may be nested inside other body elements. Use 4 spaces
per indent level.</p>
</section>
<section id="literal-blocks">
<h3><a class="toc-backref" href="#literal-blocks" role="doc-backlink">Literal Blocks</a></h3>
<p>Literal blocks are used for code samples and other preformatted text.
To indicate a literal block, preface the indented text block with
<code class="docutils literal notranslate"><span class="pre">::</span></code>” (two colons), or use the <code class="docutils literal notranslate"><span class="pre">..</span> <span class="pre">code-block::</span></code> directive.
Indent the text block by 4 spaces; the literal block continues until the end
of the indentation. For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>This is a typical paragraph. A literal block follows.
<span class="se">::</span>
<span class="s"> for a in [5, 4, 3, 2, 1]: # this is program code, shown as-is</span>
<span class="s"> print(a)</span>
<span class="s"> print(&quot;it&#39;s...&quot;)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">::</span></code>” is also recognized at the end of any paragraph; if not immediately
preceded by whitespace, one colon will remain visible in the final output:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>This is an example::
Literal block
</pre></div>
</div>
<p>By default, literal blocks will be syntax-highlighted as Python code.
For specific blocks that contain code or data in other languages/formats,
use the <code class="docutils literal notranslate"><span class="pre">..</span> <span class="pre">code-block::</span> <span class="pre">language</span></code> directive, substituting the “short name”
of the appropriate <a class="reference external" href="https://pygments.org/docs/lexers/">Pygments lexer</a>
(or <code class="docutils literal notranslate"><span class="pre">text</span></code> to disable highlighting) for <code class="docutils literal notranslate"><span class="pre">language</span></code>. For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="ow">code-block</span><span class="p">::</span> rst
An example of the <span class="s">``rst``</span> lexer (i.e. <span class="ge">*reStructuredText*</span>).
</pre></div>
</div>
<p>For PEPs that predominantly contain literal blocks of a specific language,
use the <code class="docutils literal notranslate"><span class="pre">..</span> <span class="pre">highlight::</span> <span class="pre">language</span></code> directive with the appropriate <code class="docutils literal notranslate"><span class="pre">language</span></code>
at the top of the PEP body (below the headers and above the Abstract).
All literal blocks will then be treated as that language,
unless specified otherwise in the specific <code class="docutils literal notranslate"><span class="pre">..</span> <span class="pre">code-block</span></code>. For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="ow">highlight</span><span class="p">::</span> c
<span class="gh">Abstract</span>
<span class="gh">========</span>
Here&#39;s some C code::
printf(&quot;Hello, World!\n&quot;);
</pre></div>
</div>
</section>
<section id="lists">
<h3><a class="toc-backref" href="#lists" role="doc-backlink">Lists</a></h3>
<p>Bullet list items begin with one of “-”, “*”, or “+” (hyphen,
asterisk, or plus sign), followed by whitespace and the list item
body. List item bodies must be left-aligned and indented relative to
the bullet; the text immediately after the bullet determines the
indentation. For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>This paragraph is followed by a list.
<span class="m">*</span> This is the first bullet list item. The blank line above the
first list item is required; blank lines between list items
(such as below this paragraph) are optional.
<span class="m">*</span> This is the first paragraph in the second item in the list.
This is the second paragraph in the second item in the list.
The blank line above this paragraph is required. The left edge
of this paragraph lines up with the paragraph above, both
indented relative to the bullet.
<span class="m">-</span> This is a sublist. The bullet lines up with the left edge of
the text blocks above. A sublist is a new list so requires a
blank line above and below.
<span class="m">*</span> This is the third item of the main list.
This paragraph is not part of the list.
</pre></div>
</div>
<p>Enumerated (numbered) list items are similar, but use an enumerator
instead of a bullet. Enumerators are numbers (1, 2, 3, …), letters
(A, B, C, …; uppercase or lowercase), or Roman numerals (i, ii, iii,
iv, …; uppercase or lowercase), formatted with a period suffix
(“1.”, “2.”), parentheses (“(1)”, “(2)”), or a right-parenthesis
suffix (“1)”, “2)”). For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="m">1.</span> As with bullet list items, the left edge of paragraphs must
align.
<span class="m">2.</span> Each list item may contain multiple paragraphs, sublists, etc.
This is the second paragraph of the second list item.
a) Enumerated lists may be nested.
b) Blank lines may be omitted between list items.
</pre></div>
</div>
<p>Definition lists are written like this:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>what
Definition lists associate a term with a definition.
how
The term is a one-line phrase, and the definition is one
or more paragraphs or body elements, indented relative to
the term.
</pre></div>
</div>
</section>
<section id="tables">
<h3><a class="toc-backref" href="#tables" role="doc-backlink">Tables</a></h3>
<p>Simple tables are easy and compact:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>===== ===== =======
A B A and B
===== ===== =======
False False False
True False False
False True False
True True True
===== ===== =======
</pre></div>
</div>
<p>There must be at least two columns in a table (to differentiate from
section titles). Column spans use underlines of hyphens (“Inputs”
spans the first two columns):</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>===== ===== ======
Inputs Output
------------ ------
A B A or B
===== ===== ======
False False False
True False True
False True True
True True True
===== ===== ======
</pre></div>
</div>
<p>Text in a first-column cell starts a new row. No text in the first
column indicates a continuation line; the rest of the cells may
consist of multiple lines. For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>===== =========================
col 1 col 2
===== =========================
1 Second column of row 1.
2 Second column of row 2.
Second line of paragraph.
3 - Second column of row 3.
<span class="m">-</span> Second item in bullet
list (row 3, column 2).
===== =========================
</pre></div>
</div>
</section>
<section id="hyperlinks">
<h3><a class="toc-backref" href="#hyperlinks" role="doc-backlink">Hyperlinks</a></h3>
<p>When referencing an external web page in the body of a PEP, you should
include the title of the page or a suitable description in the text, with
either an inline hyperlink or a separate explicit target with the URL.
Do not include bare URLs in the body text of the PEP, and use HTTPS
links wherever available.</p>
<p>Hyperlink references use backquotes and a trailing underscore to mark
up the reference text; backquotes are optional if the reference text
is a single word. For example, to reference a hyperlink target named
<code class="docutils literal notranslate"><span class="pre">Python</span> <span class="pre">website</span></code>, you would write:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>In this paragraph, we refer to the <span class="s">`Python website`_</span>.
</pre></div>
</div>
<p>If you intend to only reference a link once, and want to define it inline
with the text, insert the link into angle brackets (<code class="docutils literal notranslate"><span class="pre">&lt;&gt;</span></code>) after the text
you want to link, but before the closing backtick, with a space between the
text and the opening backtick. You should also use a double-underscore after
the closing backtick instead of a single one, which makes it an anonymous
reference to avoid conflicting with other target names. For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>Visit the <span class="s">`website </span><span class="si">&lt;https://www.python.org/&gt;</span><span class="s">`__</span> for more.
</pre></div>
</div>
<p>If you want to use one link multiple places with different linked text,
or want to ensure you dont have to update your link target names when
changing the linked text, include the target name within angle brackets
following the text to link, <em>with an underscore after the target name
but before the closing angle bracket</em> (or the link <strong>will not work</strong>).
For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>For further examples, see the <span class="s">`documentation </span><span class="si">&lt;pydocs_&gt;</span><span class="s">`_</span>.
</pre></div>
</div>
<p>An explicit target provides the URL. Put targets in the Footnotes section
at the end of the PEP, or immediately after the paragraph with the reference.
Hyperlink targets begin with two periods and a space (the “explicit
markup start”), followed by a leading underscore, the reference text,
a colon, and the URL.</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="nt">_Python web site:</span> https://www.python.org/
<span class="p">..</span> <span class="nt">_pydocs:</span> https://docs.python.org/
</pre></div>
</div>
<p>The reference text and the target text must match (although the match
is case-insensitive and ignores differences in whitespace). Note that
the underscore trails the reference text but precedes the target text.
If you think of the underscore as a right-pointing arrow, it points
<em>away</em> from the reference and <em>toward</em> the target.</p>
</section>
<section id="internal-and-pep-rfc-links">
<h3><a class="toc-backref" href="#internal-and-pep-rfc-links" role="doc-backlink">Internal and PEP/RFC Links</a></h3>
<p>The same mechanism as hyperlinks can be used for internal references.
Every unique section title implicitly defines an internal hyperlink target.
We can make a link to the Abstract section like this:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>Here is a hyperlink reference to the <span class="s">`Abstract`_</span> section. The
backquotes are optional since the reference text is a single word;
we can also just write: Abstract_.
</pre></div>
</div>
<p>To refer to PEPs or RFCs, always use the <code class="docutils literal notranslate"><span class="pre">:pep:</span></code> and <code class="docutils literal notranslate"><span class="pre">:rfc:</span></code> roles,
never hardcoded URLs.
For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>See <span class="na">:pep:</span><span class="nv">`1`</span> for more information on how to write a PEP,
and <span class="na">:pep:</span><span class="nv">`the Hyperlink section of PEP 12 &lt;12#hyperlinks&gt;`</span> for how to link.
</pre></div>
</div>
<p>This renders as:</p>
<blockquote>
<div>See <a class="pep reference internal" href="../pep-0001/" title="PEP 1 PEP Purpose and Guidelines">PEP 1</a> for more information on how to write a PEP,
and <a class="pep reference internal" href="../pep-0012/#hyperlinks" title="PEP 12 Sample reStructuredText PEP Template § Hyperlinks">the Hyperlink section of PEP 12</a> for how to link.</div></blockquote>
<p>PEP numbers in the text are never padded, and there is a space (not a dash)
between “PEP” or “RFC” and the number; the above roles will take care of
that for you.</p>
</section>
<section id="footnotes">
<h3><a class="toc-backref" href="#footnotes" role="doc-backlink">Footnotes</a></h3>
<p>Footnote references consist of a left square bracket, a label, a
right square bracket, and a trailing underscore.
Instead of a number, use a label of the
form “#word”, where “word” is a mnemonic consisting of alphanumerics
plus internal hyphens, underscores, and periods (no whitespace or
other characters are allowed).
For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span>Refer to The TeXbook <span class="s">[#TeXbook]_</span> for more information.
</pre></div>
</div>
<p>which renders as</p>
<blockquote>
<div>Refer to The TeXbook <a class="footnote-reference brackets" href="#texbook" id="id1">[1]</a> for more information.</div></blockquote>
<p>Whitespace must precede the footnote reference. Leave a space between
the footnote reference and the preceding word.</p>
<p>Use footnotes for additional notes, explanations and caveats, as well as
for references to books and other sources not readily available online.
Native reST hyperlink targets or inline hyperlinks in the text should be
used in preference to footnotes for including URLs to online resources.</p>
<p>Footnotes begin with “.. “ (the explicit
markup start), followed by the footnote marker (no underscores),
followed by the footnote body. For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="nt">[#TeXbook]</span> Donald Knuth&#39;s <span class="ge">*The TeXbook*</span>, pages 195 and 196.
</pre></div>
</div>
<p>which renders as</p>
<blockquote>
<div><aside class="footnote-list brackets">
<aside class="footnote brackets" id="texbook" role="doc-footnote">
<dt class="label" id="texbook">[<a href="#id1">1</a>]</dt>
<dd>Donald Knuths <em>The TeXbook</em>, pages 195 and 196.</aside>
</aside>
</div></blockquote>
<p>Footnotes and footnote references will be numbered automatically, and
the numbers will always match.</p>
</section>
<section id="images">
<h3><a class="toc-backref" href="#images" role="doc-backlink">Images</a></h3>
<p>If your PEP contains a diagram or other graphic, you may include it in the
processed output using the <code class="docutils literal notranslate"><span class="pre">image</span></code> directive:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="ow">image</span><span class="p">::</span> diagram.png
</pre></div>
</div>
<p>Any browser-friendly graphics format is possible; PNG should be
preferred for graphics, JPEG for photos and GIF for animations.
Currently, SVG must be avoided due to compatibility issues with the
PEP build system.</p>
<p>For accessibility and readers of the source text, you should include
a description of the image and any key information contained within
using the <code class="docutils literal notranslate"><span class="pre">:alt:</span></code> option to the <code class="docutils literal notranslate"><span class="pre">image</span></code> directive:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="ow">image</span><span class="p">::</span> dataflow.png
<span class="nc">:alt:</span> Data flows from the input module, through the &quot;black box&quot;
module, and finally into (and through) the output module.
</pre></div>
</div>
</section>
<section id="comments">
<h3><a class="toc-backref" href="#comments" role="doc-backlink">Comments</a></h3>
<p>A comment is an indented block of arbitrary text immediately
following an explicit markup start: two periods and whitespace. Leave
the “..” on a line by itself to ensure that the comment is not
misinterpreted as another explicit markup construct. Comments are not
visible in the processed document. For example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="c">..</span>
<span class="c"> This section should be updated in the final PEP.</span>
<span class="c"> Ensure the date is accurate.</span>
</pre></div>
</div>
</section>
<section id="escaping-mechanism">
<h3><a class="toc-backref" href="#escaping-mechanism" role="doc-backlink">Escaping Mechanism</a></h3>
<p>reStructuredText uses backslashes (”<code class="docutils literal notranslate"><span class="pre">\</span></code>”) to override the special
meaning given to markup characters and get the literal characters
themselves. To get a literal backslash, use an escaped backslash
(”<code class="docutils literal notranslate"><span class="pre">\\</span></code>”). There are two contexts in which backslashes have no
special meaning: <a class="reference internal" href="#literal-blocks">literal blocks</a> and inline literals (see <a class="reference internal" href="#inline-markup">Inline
Markup</a> above). In these contexts, no markup recognition is done,
and a single backslash represents a literal backslash, without having
to double up.</p>
<p>If you find that you need to use a backslash in your text, consider
using inline literals or a literal block instead.</p>
</section>
<section id="intersphinx">
<h3><a class="toc-backref" href="#intersphinx" role="doc-backlink">Intersphinx</a></h3>
<p>You can use
<a class="reference external" href="https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html">Intersphinx references</a>
to other Sphinx sites,
such as the <a class="reference external" href="https://docs.python.org/">Python documentation</a>
<a class="reference external" href="https://packaging.python.org/">packaging.python.org</a>,
and <a class="reference external" href="https://typing.readthedocs.io/">typing.readthedocs.io</a>,
to easily cross-reference pages, sections and Python/C objects.</p>
<p>For example,
to create a link pointing to a section of the typing docs,
you would write the following:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="na">:ref:</span><span class="nv">`type expression &lt;typing:type-expression&gt;`</span>
</pre></div>
</div>
</section>
<section id="canonical-documentation">
<h3><a class="toc-backref" href="#canonical-documentation" role="doc-backlink">Canonical Documentation</a></h3>
<p>As <a class="pep reference internal" href="../pep-0001/#pep-maintenance" title="PEP 1 PEP Purpose and Guidelines § PEP Maintenance">PEP 1 describes</a>,
PEPs are considered historical documents once marked Final,
and their canonical documentation/specification should be moved elsewhere.
To indicate this, use the <code class="docutils literal notranslate"><span class="pre">canonical-doc</span></code> directive
or an appropriate subclass:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">canonical-pypa-spec</span></code> for packaging standards</li>
<li><code class="docutils literal notranslate"><span class="pre">canonical-typing-spec</span></code> for typing standards</li>
</ul>
<p>Add the directive between the headers and the first section of the PEP
(typically the Abstract)
and pass as an argument an Intersphinx reference of the canonical doc/spec
(or if the target is not on a Sphinx site, a <a class="reference internal" href="#hyperlinks">reST hyperlink</a>).</p>
<p>For example,
to create a banner pointing to the <a class="reference external" href="https://docs.python.org/3/library/sqlite3.html#module-sqlite3" title="(in Python v3.12)"><code class="docutils literal notranslate"><span class="pre">sqlite3</span></code></a> docs,
you would write the following:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="ow">canonical-doc</span><span class="p">::</span> <span class="na">:mod:</span><span class="nv">`python:sqlite3`</span>
</pre></div>
</div>
<p>which would generate the banner:</p>
<blockquote>
<div><div class="pep-banner canonical-doc sticky-banner admonition important">
<p class="admonition-title">Important</p>
<p>This PEP is a historical document. The up-to-date, canonical documentation can now be found at <a class="reference external" href="https://docs.python.org/3/library/sqlite3.html#module-sqlite3" title="(in Python v3.12)"><code class="docutils literal notranslate"><span class="pre">sqlite3</span></code></a>.</p>
<p class="close-button">×</p>
<p>See <a class="pep reference internal" href="../pep-0001/" title="PEP 1 PEP Purpose and Guidelines">PEP 1</a> for how to propose changes.</p>
</div>
</div></blockquote>
<p>Or for a PyPA spec,
such as the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata" title="(in Python Packaging User Guide)"><span>Core metadata specifications</span></a>,
you would use:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="ow">canonical-pypa-spec</span><span class="p">::</span> <span class="na">:ref:</span><span class="nv">`packaging:core-metadata`</span>
</pre></div>
</div>
<p>which renders as:</p>
<blockquote>
<div><div class="pep-banner canonical-pypa-spec sticky-banner admonition attention">
<p class="admonition-title">Attention</p>
<p>This PEP is a historical document. The up-to-date, canonical spec, <a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata" title="(in Python Packaging User Guide)"><span>Core metadata specifications</span></a>, is maintained on the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/">PyPA specs page</a>.</p>
<p class="close-button">×</p>
<p>See the <a class="reference external" href="https://www.pypa.io/en/latest/specifications/#handling-fixes-and-other-minor-updates">PyPA specification update process</a> for how to propose changes.</p>
</div>
</div></blockquote>
<p>For a typing PEP that introduces no new runtime objects,
you might use something like the first one of these;
for a typing PEP that introduces a new object to the typing module at runtime,
you might use the second:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="ow">canonical-typing-spec</span><span class="p">::</span> <span class="na">:ref:</span><span class="nv">`typing:packaging-typed-libraries`</span>
<span class="p">..</span> <span class="ow">canonical-typing-spec</span><span class="p">::</span> <span class="na">:ref:</span><span class="nv">`typing:literal-types`</span> and
<span class="na">:py:data:</span><span class="nv">`typing.Literal`</span>
</pre></div>
</div>
<p>The two render as:</p>
<blockquote>
<div><div class="pep-banner canonical-typing-spec sticky-banner admonition attention">
<p class="admonition-title">Attention</p>
<p>This PEP is a historical document: see <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/distributing.html#packaging-typed-libraries" title="(in typing)"><span>Type information in libraries</span></a> for up-to-date specs and documentation. Canonical typing specs are maintained at the <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/">typing specs site</a>; runtime typing behaviour is described in the CPython documentation.</p>
<p class="close-button">×</p>
<p>See the <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/meta.html">typing specification update process</a> for how to propose changes to the typing spec.</p>
</div>
<div class="pep-banner canonical-typing-spec sticky-banner admonition attention">
<p class="admonition-title">Attention</p>
<p>This PEP is a historical document: see <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/literal.html#literal-types" title="(in typing)"><span>Literals</span></a> and
<a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.Literal" title="(in Python v3.12)"><code class="xref py py-data docutils literal notranslate"><span class="pre">typing.Literal</span></code></a> for up-to-date specs and documentation. Canonical typing specs are maintained at the <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/">typing specs site</a>; runtime typing behaviour is described in the CPython documentation.</p>
<p class="close-button">×</p>
<p>See the <a class="reference external" href="https://typing.readthedocs.io/en/latest/spec/meta.html">typing specification update process</a> for how to propose changes to the typing spec.</p>
</div>
</div></blockquote>
<p>The argument accepts arbitrary reST,
so you can include multiple linked docs/specs and name them whatever you like,
and you can also include directive content that will be inserted into the text.
The following advanced example:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="ow">canonical-doc</span><span class="p">::</span> the <span class="na">:ref:</span><span class="nv">`python:sqlite3-connection-objects`</span> and <span class="na">:exc:</span><span class="nv">`python:~sqlite3.DataError`</span> docs
Also, see the <span class="na">:ref:</span><span class="nv">`Data Persistence docs &lt;persistence&gt;`</span> for other examples.
</pre></div>
</div>
<p>would render as:</p>
<blockquote>
<div><div class="pep-banner canonical-doc sticky-banner admonition important">
<p class="admonition-title">Important</p>
<p>This PEP is a historical document. The up-to-date, canonical documentation can now be found at the <a class="reference external" href="https://docs.python.org/3/library/sqlite3.html#sqlite3-connection-objects" title="(in Python v3.12)"><span>Connection objects</span></a> and <a class="reference external" href="https://docs.python.org/3/library/sqlite3.html#sqlite3.DataError" title="(in Python v3.12)"><code class="docutils literal notranslate"><span class="pre">sqlite3.DataError</span></code></a> docs.</p>
<p class="close-button">×</p>
<p>Also, see the <a class="reference external" href="https://docs.python.org/3/library/persistence.html#persistence" title="(in Python v3.12)"><span class="xref std std-ref">Data Persistence docs</span></a> for other examples.</p>
<p>See <a class="pep reference internal" href="../pep-0001/" title="PEP 1 PEP Purpose and Guidelines">PEP 1</a> for how to propose changes.</p>
</div>
</div></blockquote>
</section>
</section>
<section id="habits-to-avoid">
<h2><a class="toc-backref" href="#habits-to-avoid" role="doc-backlink">Habits to Avoid</a></h2>
<p>Many programmers who are familiar with TeX often write quotation marks
like this:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>`single-quoted&#39; or ``double-quoted&#39;&#39;
</pre></div>
</div>
<p>Backquotes are significant in reStructuredText, so this practice
should be avoided. For ordinary text, use ordinary single-quotes or
“double-quotes”. For inline literal text (see <a class="reference internal" href="#inline-markup">Inline Markup</a>
above), use double-backquotes:</p>
<div class="highlight-rst notranslate"><div class="highlight"><pre><span></span><span class="s">``literal text: in here, anything goes!``</span>
</pre></div>
</div>
</section>
<section id="suggested-sections">
<h2><a class="toc-backref" href="#suggested-sections" role="doc-backlink">Suggested Sections</a></h2>
<p>Various sections are found to be common across PEPs and are outlined in
<a class="pep reference internal" href="../pep-0001/" title="PEP 1 PEP Purpose and Guidelines">PEP 1</a>. Those sections are provided here for convenience.</p>
<div class="code rst highlight-rst notranslate" id="template"><div class="highlight"><pre><span></span>PEP: &lt;REQUIRED: pep number&gt;
Title: &lt;REQUIRED: pep title&gt;
Author: &lt;REQUIRED: list of authors&#39; real names and optionally, email addrs&gt;
Sponsor: &lt;real name of sponsor&gt;
PEP-Delegate: &lt;PEP delegate&#39;s real name&gt;
Discussions-To: &lt;REQUIRED: URL of current canonical discussion thread&gt;
Status: &lt;REQUIRED: Draft | Active | Accepted | Provisional | Deferred | Rejected | Withdrawn | Final | Superseded&gt;
Type: &lt;REQUIRED: Standards Track | Informational | Process&gt;
Topic: &lt;Governance | Packaging | Release | Typing&gt;
Requires: &lt;pep numbers&gt;
Created: &lt;date created on, in dd-mmm-yyyy format&gt;
Python-Version: &lt;version number&gt;
Post-History: &lt;REQUIRED: dates, in dd-mmm-yyyy format, and corresponding links to PEP discussion threads&gt;
Replaces: &lt;pep number&gt;
Superseded-By: &lt;pep number&gt;
Resolution: &lt;url&gt;
<span class="gh">Abstract</span>
<span class="gh">========</span>
[A short (~200 word) description of the technical issue being addressed.]
<span class="gh">Motivation</span>
<span class="gh">==========</span>
[Clearly explain why the existing language specification is inadequate to address the problem that the PEP solves.]
<span class="gh">Rationale</span>
<span class="gh">=========</span>
[Describe why particular design decisions were made.]
<span class="gh">Specification</span>
<span class="gh">=============</span>
[Describe the syntax and semantics of any new language feature.]
<span class="gh">Backwards Compatibility</span>
<span class="gh">=======================</span>
[Describe potential impact and severity on pre-existing code.]
<span class="gh">Security Implications</span>
<span class="gh">=====================</span>
[How could a malicious user take advantage of this new feature?]
<span class="gh">How to Teach This</span>
<span class="gh">=================</span>
[How to teach users, new and experienced, how to apply the PEP to their work.]
<span class="gh">Reference Implementation</span>
<span class="gh">========================</span>
[Link to any existing implementation and details about its state, e.g. proof-of-concept.]
<span class="gh">Rejected Ideas</span>
<span class="gh">==============</span>
[Why certain ideas that were brought while discussing this PEP were not ultimately pursued.]
<span class="gh">Open Issues</span>
<span class="gh">===========</span>
[Any points that are still being decided/discussed.]
<span class="gh">Footnotes</span>
<span class="gh">=========</span>
[A collection of footnotes cited in the PEP, and a place to list non-inline hyperlink targets.]
<span class="gh">Copyright</span>
<span class="gh">=========</span>
This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.
</pre></div>
</div>
</section>
<section id="resources">
<h2><a class="toc-backref" href="#resources" role="doc-backlink">Resources</a></h2>
<p>Many other constructs and variations are possible,
both those supported by basic <a class="reference external" href="https://docutils.sourceforge.io/">Docutils</a>
and the extensions added by <a class="reference external" href="https://www.sphinx-doc.org/">Sphinx</a>.</p>
<p>A number of resources are available to learn more about them:</p>
<ul class="simple">
<li><a class="reference external" href="https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html">Sphinx ReStructuredText Primer</a>,
a gentle but fairly detailed introduction.</li>
<li><a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html">reStructuredText Markup Specification</a>,
the authoritative, comprehensive documentation of the basic reST syntax,
directives, roles and more.</li>
<li><a class="reference external" href="https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html">Sphinx Roles</a>
and <a class="reference external" href="https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html">Sphinx Directives</a>,
the extended constructs added by the Sphinx documentation system used to
render the PEPs to HTML.</li>
</ul>
<p>If you have questions or require assistance with writing a PEP that the above
resources dont address, ping <code class="docutils literal notranslate"><span class="pre">&#64;python/pep-editors</span></code> on GitHub, open an
<a class="reference external" href="https://github.com/python/peps/issues">issue on the PEPs repository</a>
or reach out to a PEP editor directly.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0012.rst">https://github.com/python/peps/blob/main/peps/pep-0012.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0012.rst">2024-06-14 23:31:40 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#how-to-use-this-template">How to Use This Template</a></li>
<li><a class="reference internal" href="#restructuredtext-pep-formatting-requirements">ReStructuredText PEP Formatting Requirements</a><ul>
<li><a class="reference internal" href="#general">General</a></li>
<li><a class="reference internal" href="#section-headings">Section Headings</a></li>
<li><a class="reference internal" href="#paragraphs">Paragraphs</a></li>
<li><a class="reference internal" href="#inline-markup">Inline Markup</a></li>
<li><a class="reference internal" href="#block-quotes">Block Quotes</a></li>
<li><a class="reference internal" href="#literal-blocks">Literal Blocks</a></li>
<li><a class="reference internal" href="#lists">Lists</a></li>
<li><a class="reference internal" href="#tables">Tables</a></li>
<li><a class="reference internal" href="#hyperlinks">Hyperlinks</a></li>
<li><a class="reference internal" href="#internal-and-pep-rfc-links">Internal and PEP/RFC Links</a></li>
<li><a class="reference internal" href="#footnotes">Footnotes</a></li>
<li><a class="reference internal" href="#images">Images</a></li>
<li><a class="reference internal" href="#comments">Comments</a></li>
<li><a class="reference internal" href="#escaping-mechanism">Escaping Mechanism</a></li>
<li><a class="reference internal" href="#intersphinx">Intersphinx</a></li>
<li><a class="reference internal" href="#canonical-documentation">Canonical Documentation</a></li>
</ul>
</li>
<li><a class="reference internal" href="#habits-to-avoid">Habits to Avoid</a></li>
<li><a class="reference internal" href="#suggested-sections">Suggested Sections</a></li>
<li><a class="reference internal" href="#resources">Resources</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0012.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

474
pep-0013/index.html Normal file
View File

@ -0,0 +1,474 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 13 Python Language Governance | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0013/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 13 Python Language Governance | peps.python.org'>
<meta property="og:description" content="This PEP defines the formal governance process for Python, and records how this has changed over time. Currently, governance is based around a steering council. The council has broad authority, which they seek to exercise as rarely as possible.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0013/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP defines the formal governance process for Python, and records how this has changed over time. Currently, governance is based around a steering council. The council has broad authority, which they seek to exercise as rarely as possible.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 13</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 13 Python Language Governance</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">The Python core team and community</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Topic<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../topic/governance/">Governance</a></dd>
<dt class="field-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">16-Dec-2018</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#current-steering-council">Current steering council</a></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#the-steering-council">The steering council</a><ul>
<li><a class="reference internal" href="#composition">Composition</a></li>
<li><a class="reference internal" href="#mandate">Mandate</a></li>
<li><a class="reference internal" href="#powers">Powers</a></li>
<li><a class="reference internal" href="#electing-the-council">Electing the council</a></li>
<li><a class="reference internal" href="#term">Term</a></li>
<li><a class="reference internal" href="#vacancies">Vacancies</a></li>
<li><a class="reference internal" href="#conflicts-of-interest">Conflicts of interest</a></li>
<li><a class="reference internal" href="#ejecting-core-team-members">Ejecting core team members</a></li>
<li><a class="reference internal" href="#vote-of-no-confidence">Vote of no confidence</a></li>
</ul>
</li>
<li><a class="reference internal" href="#the-core-team">The core team</a><ul>
<li><a class="reference internal" href="#role">Role</a></li>
<li><a class="reference internal" href="#prerogatives">Prerogatives</a></li>
<li><a class="reference internal" href="#membership">Membership</a></li>
</ul>
</li>
<li><a class="reference internal" href="#changing-this-document">Changing this document</a></li>
</ul>
</li>
<li><a class="reference internal" href="#history">History</a><ul>
<li><a class="reference internal" href="#creation-of-this-document">Creation of this document</a></li>
<li><a class="reference internal" href="#history-of-council-elections">History of council elections</a></li>
<li><a class="reference internal" href="#history-of-amendments">History of amendments</a></li>
</ul>
</li>
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP defines the formal governance process for Python, and records
how this has changed over time. Currently, governance is based around
a steering council. The council has broad authority, which they seek
to exercise as rarely as possible.</p>
</section>
<section id="current-steering-council">
<h2><a class="toc-backref" href="#current-steering-council" role="doc-backlink">Current steering council</a></h2>
<p>The 2024 term steering council consists of:</p>
<ul class="simple">
<li>Barry Warsaw</li>
<li>Emily Morehouse</li>
<li>Gregory P. Smith</li>
<li>Pablo Galindo Salgado</li>
<li>Thomas Wouters</li>
</ul>
<p>Per the results of the vote tracked in <a class="pep reference internal" href="../pep-8105/" title="PEP 8105 2024 Term Steering Council election">PEP 8105</a>.</p>
<p>The core team consists of those listed in the private
<a class="reference external" href="https://github.com/python/voters/">https://github.com/python/voters/</a> repository which is publicly
shared via <a class="reference external" href="https://devguide.python.org/developers/">https://devguide.python.org/developers/</a>.</p>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<section id="the-steering-council">
<h3><a class="toc-backref" href="#the-steering-council" role="doc-backlink">The steering council</a></h3>
<section id="composition">
<h4><a class="toc-backref" href="#composition" role="doc-backlink">Composition</a></h4>
<p>The steering council is a 5-person committee.</p>
</section>
<section id="mandate">
<h4><a class="toc-backref" href="#mandate" role="doc-backlink">Mandate</a></h4>
<p>The steering council shall work to:</p>
<ul class="simple">
<li>Maintain the quality and stability of the Python language and
CPython interpreter,</li>
<li>Make contributing as accessible, inclusive, and sustainable as
possible,</li>
<li>Formalize and maintain the relationship between the core team and
the PSF,</li>
<li>Establish appropriate decision-making processes for PEPs,</li>
<li>Seek consensus among contributors and the core team before acting in
a formal capacity,</li>
<li>Act as a “court of final appeal” for decisions where all other
methods have failed.</li>
</ul>
</section>
<section id="powers">
<h4><a class="toc-backref" href="#powers" role="doc-backlink">Powers</a></h4>
<p>The council has broad authority to make decisions about the project.
For example, they can:</p>
<ul class="simple">
<li>Accept or reject PEPs</li>
<li>Enforce or update the projects code of conduct</li>
<li>Work with the PSF to manage any project assets</li>
<li>Delegate parts of their authority to other subcommittees or
processes</li>
</ul>
<p>However, they cannot modify this PEP, or affect the membership of the
core team, except via the mechanisms specified in this PEP.</p>
<p>The council should look for ways to use these powers as little as
possible. Instead of voting, its better to seek consensus. Instead of
ruling on individual PEPs, its better to define a standard process
for PEP decision making (for example, by accepting one of the other
801x series of PEPs). Its better to establish a Code of Conduct
committee than to rule on individual cases. And so on.</p>
<p>To use its powers, the council votes. Every council member must either
vote or explicitly abstain. Members with conflicts of interest on a
particular vote must abstain. Passing requires a strict majority of
non-abstaining council members.</p>
<p>Whenever possible, the councils deliberations and votes shall be held
in public.</p>
</section>
<section id="electing-the-council">
<h4><a class="toc-backref" href="#electing-the-council" role="doc-backlink">Electing the council</a></h4>
<p>A council election consists of two phases:</p>
<ul class="simple">
<li>Phase 1: Candidates advertise their interest in serving. Candidates
must be nominated by a core team member. Self-nominations are
allowed.</li>
<li>Phase 2: Each core team member can vote for zero or more of the
candidates. Voting is performed anonymously. Candidates are ranked
by the total number of votes they receive. If a tie occurs, it may
be resolved by mutual agreement among the candidates, or else the
winner will be chosen at random.</li>
</ul>
<p>Each phase lasts one to two weeks, at the outgoing councils discretion.
For the initial election, both phases will last two weeks.</p>
<p>The election process is managed by a returns officer nominated by the
outgoing steering council. For the initial election, the returns
officer will be nominated by the PSF Executive Director.</p>
<p>The council should ideally reflect the diversity of Python
contributors and users, and core team members are encouraged to vote
accordingly.</p>
</section>
<section id="term">
<h4><a class="toc-backref" href="#term" role="doc-backlink">Term</a></h4>
<p>A new council is elected after each feature release. Each councils
term runs from when their election results are finalized until the
next councils term starts. There are no term limits.</p>
</section>
<section id="vacancies">
<h4><a class="toc-backref" href="#vacancies" role="doc-backlink">Vacancies</a></h4>
<p>Council members may resign their position at any time.</p>
<p>Whenever there is a vacancy during the regular council term, the
council may vote to appoint a replacement to serve out the rest of the
term.</p>
<p>If a council member drops out of touch and cannot be contacted for a
month or longer, then the rest of the council may vote to replace
them.</p>
</section>
<section id="conflicts-of-interest">
<h4><a class="toc-backref" href="#conflicts-of-interest" role="doc-backlink">Conflicts of interest</a></h4>
<p>While we trust council members to act in the best interests of Python
rather than themselves or their employers, the mere appearance of any
one company dominating Python development could itself be harmful and
erode trust. In order to avoid any appearance of conflict of interest,
at most 2 members of the council can work for any single employer.</p>
<p>In a council election, if 3 of the top 5 vote-getters work for the
same employer, then whichever of them ranked lowest is disqualified
and the 6th-ranking candidate moves up into 5th place; this is
repeated until a valid council is formed.</p>
<p>During a council term, if changing circumstances cause this rule to be
broken (for instance, due to a council member changing employment),
then one or more council members must resign to remedy the issue, and
the resulting vacancies can then be filled as normal.</p>
</section>
<section id="ejecting-core-team-members">
<h4><a class="toc-backref" href="#ejecting-core-team-members" role="doc-backlink">Ejecting core team members</a></h4>
<p>In exceptional circumstances, it may be necessary to remove someone
from the core team against their will. (For example: egregious and
ongoing code of conduct violations.) This can be accomplished by a
steering council vote, but unlike other steering council votes, this
requires at least a two-thirds majority. With 5 members voting, this
means that a 3:2 vote is insufficient; 4:1 in favor is the minimum
required for such a vote to succeed. In addition, this is the one
power of the steering council which cannot be delegated, and this
power cannot be used while a vote of no confidence is in process.</p>
<p>If the ejected core team member is also on the steering council, then
they are removed from the steering council as well.</p>
</section>
<section id="vote-of-no-confidence">
<h4><a class="toc-backref" href="#vote-of-no-confidence" role="doc-backlink">Vote of no confidence</a></h4>
<p>In exceptional circumstances, the core team may remove a sitting
council member, or the entire council, via a vote of no confidence.</p>
<p>A no-confidence vote is triggered when a core team member calls for
one publicly on an appropriate project communication channel, and
another core team member seconds the proposal.</p>
<p>The vote lasts for two weeks. Core team members vote for or against.
If at least two thirds of voters express a lack of confidence, then
the vote succeeds.</p>
<p>There are two forms of no-confidence votes: those targeting a single
member, and those targeting the council as a whole. The initial call
for a no-confidence vote must specify which type is intended. If a
single-member vote succeeds, then that member is removed from the
council and the resulting vacancy can be handled in the usual way. If
a whole-council vote succeeds, the council is dissolved and a new
council election is triggered immediately.</p>
</section>
</section>
<section id="the-core-team">
<h3><a class="toc-backref" href="#the-core-team" role="doc-backlink">The core team</a></h3>
<section id="role">
<h4><a class="toc-backref" href="#role" role="doc-backlink">Role</a></h4>
<p>The core team is the group of trusted volunteers who manage Python.
They assume many roles required to achieve the projects goals,
especially those that require a high level of trust. They make the
decisions that shape the future of the project.</p>
<p>Core team members are expected to act as role models for the community
and custodians of the project, on behalf of the community and all
those who rely on Python.</p>
<p>They will intervene, where necessary, in online discussions or at
official Python events on the rare occasions that a situation arises
that requires intervention.</p>
<p>They have authority over the Python Project infrastructure, including
the Python Project website itself, the Python GitHub organization and
repositories, the bug tracker, the mailing lists, IRC channels, etc.</p>
</section>
<section id="prerogatives">
<h4><a class="toc-backref" href="#prerogatives" role="doc-backlink">Prerogatives</a></h4>
<p>Core team members may participate in formal votes, typically to nominate new
team members and to elect the steering council.</p>
</section>
<section id="membership">
<h4><a class="toc-backref" href="#membership" role="doc-backlink">Membership</a></h4>
<p>Python core team members demonstrate:</p>
<ul class="simple">
<li>a good grasp of the philosophy of the Python Project</li>
<li>a solid track record of being constructive and helpful</li>
<li>significant contributions to the projects goals, in any form</li>
<li>willingness to dedicate some time to improving Python</li>
</ul>
<p>As the project matures, contributions go beyond code. Heres an
incomplete list of areas where contributions may be considered for
joining the core team, in no particular order:</p>
<ul class="simple">
<li>Working on community management and outreach</li>
<li>Providing support on the mailing lists and on IRC</li>
<li>Triaging tickets</li>
<li>Writing patches (code, docs, or tests)</li>
<li>Reviewing patches (code, docs, or tests)</li>
<li>Participating in design decisions</li>
<li>Providing expertise in a particular domain (security, i18n, etc.)</li>
<li>Managing the continuous integration infrastructure</li>
<li>Managing the servers (website, tracker, documentation, etc.)</li>
<li>Maintaining related projects (alternative interpreters, core
infrastructure like packaging, etc.)</li>
<li>Creating visual designs</li>
</ul>
<p>Core team membership acknowledges sustained and valuable efforts that
align well with the philosophy and the goals of the Python project.</p>
<p>It is granted by receiving at least two-thirds positive votes in a
core team vote that is open for one week and is not vetoed by the
steering council.</p>
<p>Core team members are always looking for promising contributors,
teaching them how the project is managed, and submitting their names
to the core teams vote when theyre ready.</p>
<p>Theres no time limit on core team membership. However, in order to
provide the general public with a reasonable idea of how many people
maintain Python, core team members who have stopped contributing are
encouraged to declare themselves as “inactive”. Those who havent made
any non-trivial contribution in two years may be asked to move
themselves to this category, and moved there if they dont respond. To
record and honor their contributions, inactive team members will
continue to be listed alongside active core team members; and, if they
later resume contributing, they can switch back to active status at
will. While someone is in inactive status, though, they lose their
active privileges like voting or nominating for the steering council,
and commit access.</p>
<p>The initial active core team members will consist of everyone
currently listed in the <a class="reference external" href="https://github.com/orgs/python/teams/python-core/members">“Python core” team on GitHub</a> (access
granted for core members only), and the
initial inactive members will consist of everyone else who has been a
committer in the past.</p>
</section>
</section>
<section id="changing-this-document">
<h3><a class="toc-backref" href="#changing-this-document" role="doc-backlink">Changing this document</a></h3>
<p>Changes to this document require at least a two-thirds majority of
votes cast in a core team vote which should be open for two weeks.</p>
</section>
</section>
<section id="history">
<h2><a class="toc-backref" href="#history" role="doc-backlink">History</a></h2>
<section id="creation-of-this-document">
<h3><a class="toc-backref" href="#creation-of-this-document" role="doc-backlink">Creation of this document</a></h3>
<p>The Python project was started by Guido van Rossum, who served as its
Benevolent Dictator for Life (BDFL) from inception until July 2018,
when he <a class="reference external" href="https://mail.python.org/pipermail/python-committers/2018-July/005664.html">stepped down</a>.</p>
<p>After discussion, a number of proposals were put forward for a new
governance model, and the core devs voted to choose between them. The
overall process is described in <a class="pep reference internal" href="../pep-8000/" title="PEP 8000 Python Language Governance Proposal Overview">PEP 8000</a> and <a class="pep reference internal" href="../pep-8001/" title="PEP 8001 Python Governance Voting Process">PEP 8001</a>, a review of
other projects was performed in <a class="pep reference internal" href="../pep-8002/" title="PEP 8002 Open Source Governance Survey">PEP 8002</a>, and the proposals themselves
were written up as the 801x series of PEPs. Eventually the proposal in
<a class="pep reference internal" href="../pep-8016/" title="PEP 8016 The Steering Council Model">PEP 8016</a> was <a class="reference external" href="https://discuss.python.org/t/python-governance-vote-december-2018-results/546">selected</a>
as the new governance model, and was used to create the initial
version of this PEP. The 8000-series PEPs are preserved for historical
reference (and in particular, <a class="pep reference internal" href="../pep-8016/" title="PEP 8016 The Steering Council Model">PEP 8016</a> contains additional rationale
and links to contemporary discussions), but this PEP is now the
official reference, and will evolve following the rules described
herein.</p>
</section>
<section id="history-of-council-elections">
<h3><a class="toc-backref" href="#history-of-council-elections" role="doc-backlink">History of council elections</a></h3>
<ul class="simple">
<li>January 2019: <a class="pep reference internal" href="../pep-8100/" title="PEP 8100 January 2019 Steering Council election">PEP 8100</a></li>
<li>December 2019: <a class="pep reference internal" href="../pep-8101/" title="PEP 8101 2020 Term Steering Council election">PEP 8101</a></li>
<li>December 2020: <a class="pep reference internal" href="../pep-8102/" title="PEP 8102 2021 Term Steering Council election">PEP 8102</a></li>
<li>December 2021: <a class="pep reference internal" href="../pep-8103/" title="PEP 8103 2022 Term Steering Council election">PEP 8103</a></li>
<li>December 2022: <a class="pep reference internal" href="../pep-8104/" title="PEP 8104 2023 Term Steering Council election">PEP 8104</a></li>
<li>December 2023: <a class="pep reference internal" href="../pep-8105/" title="PEP 8105 2024 Term Steering Council election">PEP 8105</a></li>
</ul>
</section>
<section id="history-of-amendments">
<h3><a class="toc-backref" href="#history-of-amendments" role="doc-backlink">History of amendments</a></h3>
<p>2019-04-17: Added the vote length for core devs and changes to this document.</p>
</section>
</section>
<section id="acknowledgements">
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
<p>This PEP began as <a class="pep reference internal" href="../pep-8016/" title="PEP 8016 The Steering Council Model">PEP 8016</a>, which was written by Nathaniel J. Smith
and Donald Stufft, based on a Django governance document written by
Aymeric Augustin, and incorporated feedback and assistance from
numerous others.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0013.rst">https://github.com/python/peps/blob/main/peps/pep-0013.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0013.rst">2023-12-12 12:20:36 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#current-steering-council">Current steering council</a></li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#the-steering-council">The steering council</a><ul>
<li><a class="reference internal" href="#composition">Composition</a></li>
<li><a class="reference internal" href="#mandate">Mandate</a></li>
<li><a class="reference internal" href="#powers">Powers</a></li>
<li><a class="reference internal" href="#electing-the-council">Electing the council</a></li>
<li><a class="reference internal" href="#term">Term</a></li>
<li><a class="reference internal" href="#vacancies">Vacancies</a></li>
<li><a class="reference internal" href="#conflicts-of-interest">Conflicts of interest</a></li>
<li><a class="reference internal" href="#ejecting-core-team-members">Ejecting core team members</a></li>
<li><a class="reference internal" href="#vote-of-no-confidence">Vote of no confidence</a></li>
</ul>
</li>
<li><a class="reference internal" href="#the-core-team">The core team</a><ul>
<li><a class="reference internal" href="#role">Role</a></li>
<li><a class="reference internal" href="#prerogatives">Prerogatives</a></li>
<li><a class="reference internal" href="#membership">Membership</a></li>
</ul>
</li>
<li><a class="reference internal" href="#changing-this-document">Changing this document</a></li>
</ul>
</li>
<li><a class="reference internal" href="#history">History</a><ul>
<li><a class="reference internal" href="#creation-of-this-document">Creation of this document</a></li>
<li><a class="reference internal" href="#history-of-council-elections">History of council elections</a></li>
<li><a class="reference internal" href="#history-of-amendments">History of amendments</a></li>
</ul>
</li>
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0013.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

176
pep-0020/index.html Normal file
View File

@ -0,0 +1,176 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 20 The Zen of Python | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0020/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 20 The Zen of Python | peps.python.org'>
<meta property="og:description" content="Long time Pythoneer Tim Peters succinctly channels the BDFLs guiding principles for Pythons design into 20 aphorisms, only 19 of which have been written down.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0020/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Long time Pythoneer Tim Peters succinctly channels the BDFLs guiding principles for Pythons design into 20 aphorisms, only 19 of which have been written down.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 20</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 20 The Zen of Python</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Tim Peters &lt;tim.peters&#32;&#97;t&#32;gmail.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">19-Aug-2004</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd">22-Aug-2004</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#the-zen-of-python">The Zen of Python</a></li>
<li><a class="reference internal" href="#easter-egg">Easter Egg</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Long time Pythoneer Tim Peters succinctly channels the BDFLs guiding
principles for Pythons design into 20 aphorisms, only 19 of which
have been written down.</p>
</section>
<section id="the-zen-of-python">
<h2><a class="toc-backref" href="#the-zen-of-python" role="doc-backlink">The Zen of Python</a></h2>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren&#39;t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you&#39;re Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it&#39;s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let&#39;s do more of those!
</pre></div>
</div>
</section>
<section id="easter-egg">
<h2><a class="toc-backref" href="#easter-egg" role="doc-backlink">Easter Egg</a></h2>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">this</span>
</pre></div>
</div>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<p>Originally posted to <a class="reference external" href="mailto:comp&#46;lang&#46;python/python-list&#37;&#52;&#48;python&#46;org">comp<span>&#46;</span>lang<span>&#46;</span>python/python-list<span>&#64;</span>python<span>&#46;</span>org</a> under a
thread called <a class="reference external" href="https://groups.google.com/d/msg/comp.lang.python/B_VxeTBClM0/L8W9KlsiriUJ">“The Way of Python”</a></p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0020.rst">https://github.com/python/peps/blob/main/peps/pep-0020.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0020.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#the-zen-of-python">The Zen of Python</a></li>
<li><a class="reference internal" href="#easter-egg">Easter Egg</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0020.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

377
pep-0042/index.html Normal file
View File

@ -0,0 +1,377 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 42 Feature Requests | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0042/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 42 Feature Requests | peps.python.org'>
<meta property="og:description" content="This PEP contains a list of feature requests that may be considered for future versions of Python. Large feature requests should not be included here, but should be described in separate PEPs; however a large feature request that doesnt have its own P...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0042/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP contains a list of feature requests that may be considered for future versions of Python. Large feature requests should not be included here, but should be described in separate PEPs; however a large feature request that doesnt have its own P...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 42</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 42 Feature Requests</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Jeremy Hylton &lt;jeremy&#32;&#97;t&#32;alum.mit.edu&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP describing or proposing a change to a Python community process, workflow or governance">Process</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">12-Sep-2000</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#core-language-builtins">Core Language / Builtins</a></li>
<li><a class="reference internal" href="#standard-library">Standard Library</a></li>
<li><a class="reference internal" href="#c-api-wishes">C API wishes</a></li>
<li><a class="reference internal" href="#tools">Tools</a></li>
<li><a class="reference internal" href="#building-and-installing">Building and Installing</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated withdrawn admonition important">
<p class="admonition-title">Important</p>
<p>This PEP has been withdrawn.</p>
<p class="close-button">×</p>
<p>It is <a class="reference external" href="https://github.com/python/peps/pull/108#issuecomment-249603204">obsolete</a>.
All new feature requests should either go to the <a class="reference external" href="https://github.com/python/cpython/issues">Python bug tracker</a>
for very simple requests or the <a class="reference external" href="https://discuss.python.org/c/ideas/6">Ideas Discourse category</a> for
everything else. The rest of this document is retained for historical
purposes only.</p>
<p></p>
</div>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP contains a list of feature requests that may be considered
for future versions of Python. Large feature requests should not be
included here, but should be described in separate PEPs; however a
large feature request that doesnt have its own PEP can be listed here
until its own PEP is created. See <a class="pep reference internal" href="../pep-0000/" title="PEP 0 Index of Python Enhancement Proposals (PEPs)">PEP 0</a> for details.</p>
<p>This PEP was created to allow us to close bug reports that are really
feature requests. Marked as Open, they distract from the list of real
bugs (which should ideally be less than a page). Marked as Closed,
they tend to be forgotten. The procedure now is: if a bug report is
really a feature request, add the feature request to this PEP; mark
the bug as “feature request”, “later”, and “closed”; and add a comment
to the bug saying that this is the case (mentioning the PEP
explicitly). It is also acceptable to move large feature requests
directly from the bugs database to a separate PEP.</p>
<p>This PEP should really be separated into four different categories
(categories due to Laura Creighton):</p>
<ol class="arabic">
<li>BDFL rejects as a bad idea. Dont come back with it.</li>
<li>BDFL will put in if somebody writes the code. (Or at any rate,
BDFL will say change this and I will put it in if you show up
with code.)<p>possibly divided into:</p>
<blockquote>
<div><ol class="loweralpha simple">
<li>BDFL would really like to see some code!</li>
<li>BDFL is never going to be enthusiastic about this, but
will work it in when its easy.</li>
</ol>
</div></blockquote>
</li>
<li>If you show up with code, BDFL will make a pronouncement. It might
be ICK.</li>
<li>This is too vague. This is rejected, but only on the grounds of
vagueness. If you like this enhancement, make a new PEP.</li>
</ol>
</section>
<section id="core-language-builtins">
<h2><a class="toc-backref" href="#core-language-builtins" role="doc-backlink">Core Language / Builtins</a></h2>
<ul>
<li>The parser should handle more deeply nested parse trees.<p>The following will fail <code class="docutils literal notranslate"><span class="pre">eval(&quot;[&quot;*50</span></code> + <code class="docutils literal notranslate"><span class="pre">&quot;]&quot;*50)</span></code> because
the parser has a hard-coded limit on stack size. This limit should
be raised or removed. Removal would be hard because the current
compiler can overflow the C stack if the nesting is too deep.</p>
<p><a class="reference external" href="https://bugs.python.org/issue215555">https://bugs.python.org/issue215555</a></p>
</li>
<li>Non-accidental IEEE-754 support (Infs, NaNs, settable traps, etc).
Big project.</li>
<li>Windows: Trying to create (or even access) files with certain
magic names can hang or crash Windows systems. This is really a
bug in the OSes, but some apps try to shield users from it. When
it happens, the symptoms are very confusing.<p>Hang using files named prn.txt, etc <a class="reference external" href="https://bugs.python.org/issue481171">https://bugs.python.org/issue481171</a></p>
</li>
<li>eval and free variables: It might be useful if there was a way to
pass bindings for free variables to eval when a code object with
free variables is passed. <a class="reference external" href="https://bugs.python.org/issue443866">https://bugs.python.org/issue443866</a></li>
</ul>
</section>
<section id="standard-library">
<h2><a class="toc-backref" href="#standard-library" role="doc-backlink">Standard Library</a></h2>
<ul>
<li>The urllib module should support proxies which require
authentication. See SourceForge bug #210619 for information:<p><a class="reference external" href="https://bugs.python.org/issue210619">https://bugs.python.org/issue210619</a></p>
</li>
<li>os.rename() should be modified to handle EXDEV errors on platforms
that dont allow rename() to operate across filesystem boundaries
by copying the file over and removing the original. Linux is one
system that requires this treatment.<p><a class="reference external" href="https://bugs.python.org/issue212317">https://bugs.python.org/issue212317</a></p>
</li>
<li>signal handling doesnt always work as expected. E.g. if
sys.stdin.readline() is interrupted by a (returning) signal
handler, it returns “”. It would be better to make it raise an
exception (corresponding to EINTR) or to restart. But these
changes would have to applied to all places that can do blocking
interruptible I/O. So its a big project.<p><a class="reference external" href="https://bugs.python.org/issue210599">https://bugs.python.org/issue210599</a></p>
</li>
<li>Extend Windows utime to accept directory paths.<p><a class="reference external" href="https://bugs.python.org/issue214245">https://bugs.python.org/issue214245</a></p>
</li>
<li>Extend copy.py to module &amp; function types.<p><a class="reference external" href="https://bugs.python.org/issue214553">https://bugs.python.org/issue214553</a></p>
</li>
<li>Better checking for bad input to <code class="docutils literal notranslate"><span class="pre">marshal.load*().</span></code><p><a class="reference external" href="https://bugs.python.org/issue214754">https://bugs.python.org/issue214754</a></p>
</li>
<li>rfc822.py should be more lenient than the spec in the types of
address fields it parses. Specifically, an invalid address of the
form “From: Amazon.com &lt;<a class="reference external" href="mailto:delivers-news2&#37;&#52;&#48;amazon&#46;com">delivers-news2<span>&#64;</span>amazon<span>&#46;</span>com</a>&gt;” should be
parsed correctly.<p><a class="reference external" href="https://bugs.python.org/issue210678">https://bugs.python.org/issue210678</a></p>
</li>
<li>cgi.pys FieldStorage class should be more conservative with memory
in the face of large binary file uploads.<p><a class="reference external" href="https://bugs.python.org/issue210674">https://bugs.python.org/issue210674</a></p>
<p>There are two issues here: first, because
read_lines_to_outerboundary() uses readline() it is possible that a
large amount of data will be read into memory for a binary file
upload. This should probably look at the Content-Type header of the
section and do a chunked read if its a binary type.</p>
<p>The second issue was related to the self.lines attribute, which was
removed in revision 1.56 of cgi.py (see also):</p>
<p><a class="reference external" href="https://bugs.python.org/issue219806">https://bugs.python.org/issue219806</a></p>
</li>
<li>urllib should support proxy definitions that contain just the host
and port<p><a class="reference external" href="https://bugs.python.org/issue210849">https://bugs.python.org/issue210849</a></p>
</li>
<li>urlparse should be updated to comply with <span class="target" id="index-0"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2396.html"><strong>RFC 2396</strong></a>, which defines
optional parameters for each segment of the path.<p><a class="reference external" href="https://bugs.python.org/issue210834">https://bugs.python.org/issue210834</a></p>
</li>
<li>The exceptions raised by pickle and cPickle are currently
different; these should be unified (probably the exceptions should
be defined in a helper module thats imported by both). [No bug
report; I just thought of this.]</li>
<li>More standard library routines should support Unicode. For
example, urllib.quote() could convert Unicode strings to UTF-8 and
then do the usual %HH conversion. But this is not the only one!<p><a class="reference external" href="https://bugs.python.org/issue216716">https://bugs.python.org/issue216716</a></p>
</li>
<li>There should be a way to say that you dont mind if <code class="docutils literal notranslate"><span class="pre">str()</span></code> or
<code class="docutils literal notranslate"><span class="pre">__str__()</span></code> return a Unicode string object. Or a different function
<code class="docutils literal notranslate"><span class="pre">ustr()</span></code> has been proposed. Or something…<p><a class="reference external" href="http://sf.net/patch/?func=detailpatch&amp;patch_id=101527&amp;group_id=5470">http://sf.net/patch/?func=detailpatch&amp;patch_id=101527&amp;group_id=5470</a></p>
</li>
<li>Killing a thread from another thread. Or maybe sending a signal.
Or maybe raising an asynchronous exception.<p><a class="reference external" href="https://bugs.python.org/issue221115">https://bugs.python.org/issue221115</a></p>
</li>
<li>The debugger (pdb) should understand packages.<p><a class="reference external" href="https://bugs.python.org/issue210631">https://bugs.python.org/issue210631</a></p>
</li>
<li>Jim Fulton suggested the following:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">I</span> <span class="n">wonder</span> <span class="k">if</span> <span class="n">it</span> <span class="n">would</span> <span class="n">be</span> <span class="n">a</span> <span class="n">good</span> <span class="n">idea</span> <span class="n">to</span> <span class="n">have</span> <span class="n">a</span> <span class="n">new</span> <span class="n">kind</span> <span class="n">of</span>
<span class="n">temporary</span> <span class="n">file</span> <span class="n">that</span> <span class="n">stored</span> <span class="n">data</span> <span class="ow">in</span> <span class="n">memory</span> <span class="n">unless</span><span class="p">:</span>
<span class="o">-</span> <span class="n">The</span> <span class="n">data</span> <span class="n">exceeds</span> <span class="n">some</span> <span class="n">size</span><span class="p">,</span> <span class="ow">or</span>
<span class="o">-</span> <span class="n">Somebody</span> <span class="n">asks</span> <span class="k">for</span> <span class="n">a</span> <span class="n">fileno</span><span class="o">.</span>
<span class="n">Then</span> <span class="n">the</span> <span class="n">cgi</span> <span class="n">module</span> <span class="p">(</span><span class="ow">and</span> <span class="n">other</span> <span class="n">apps</span><span class="p">)</span> <span class="n">could</span> <span class="n">use</span> <span class="n">this</span> <span class="n">thing</span> <span class="ow">in</span> <span class="n">a</span>
<span class="n">uniform</span> <span class="n">way</span><span class="o">.</span>
</pre></div>
</div>
<p><a class="reference external" href="https://bugs.python.org/issue415692">https://bugs.python.org/issue415692</a></p>
</li>
<li>Jim Fulton pointed out that binasciis b2a_base64() function has
situations where it makes sense not to append a newline, or to
append something else than a newline.<p>Proposal:</p>
<ul class="simple">
<li>add an optional argument giving the delimiter string to be
appended, defaulting to “\n”</li>
<li>possibly special-case None as the delimiter string to avoid adding
the pad bytes too???</li>
</ul>
<p><a class="reference external" href="https://bugs.python.org/issue415694">https://bugs.python.org/issue415694</a></p>
</li>
<li>pydoc should be integrated with the HTML docs, or at least be able
to link to them.<p><a class="reference external" href="https://bugs.python.org/issue405554">https://bugs.python.org/issue405554</a></p>
</li>
<li>Distutils should deduce dependencies for .c and .h files.<p><a class="reference external" href="https://bugs.python.org/issue472881">https://bugs.python.org/issue472881</a></p>
</li>
<li>asynchat is buggy in the face of multithreading.<p><a class="reference external" href="https://bugs.python.org/issue595217">https://bugs.python.org/issue595217</a></p>
</li>
<li>It would be nice if the higher level modules (httplib, smtplib,
nntplib, etc.) had options for setting socket timeouts.<p><a class="reference external" href="https://bugs.python.org/issue723287">https://bugs.python.org/issue723287</a></p>
</li>
<li>The curses library is missing two important calls: newterm() and
delscreen()<p><a class="reference external" href="https://bugs.python.org/issue665572">https://bugs.python.org/issue665572</a>, <a class="reference external" href="http://bugs.debian.org/175590">http://bugs.debian.org/175590</a></p>
</li>
<li>It would be nice if the built-in SSL socket type could be used for
non-blocking SSL I/O. Currently packages such as Twisted which
implement async servers using SSL have to require third-party
packages such as pyopenssl.</li>
<li>reST as a standard library module</li>
<li>The import lock could use some redesign.<p><a class="reference external" href="https://bugs.python.org/issue683658">https://bugs.python.org/issue683658</a></p>
</li>
<li>A nicer API to open text files, replacing the ugly (in some
peoples eyes) “U” mode flag. Theres a proposal out there to have
a new built-in type textfile(filename, mode, encoding). (Shouldnt
it have a bufsize argument too?)</li>
<li>Support new widgets and/or parameters for Tkinter</li>
<li>For a class defined inside another class, the __name__ should be
“outer.inner”, and pickling should work. (GvR is no longer certain
this is easy or even right.)<p><a class="reference external" href="https://bugs.python.org/issue633930">https://bugs.python.org/issue633930</a></p>
</li>
<li>Decide on a clearer deprecation policy (especially for modules) and
act on it.<p><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2002-April/023165.html">https://mail.python.org/pipermail/python-dev/2002-April/023165.html</a></p>
</li>
<li>Provide alternatives for common uses of the types module; Skip
Montanaro has posted a proto-PEP for this idea:<p><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2002-May/024346.html">https://mail.python.org/pipermail/python-dev/2002-May/024346.html</a></p>
</li>
<li>Use pending deprecation for the types and string modules. This
requires providing alternatives for the parts that arent covered
yet (e.g. string.whitespace and types.TracebackType). It seems we
cant get consensus on this.</li>
<li>Lazily tracking tuples?<p><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2002-May/023926.html">https://mail.python.org/pipermail/python-dev/2002-May/023926.html</a>
<a class="reference external" href="https://bugs.python.org/issue558745">https://bugs.python.org/issue558745</a></p>
</li>
<li>Make as a keyword. It has been a pseudo-keyword long enough.
(Its deprecated in 2.5, and will become a keyword in 2.6.)</li>
</ul>
</section>
<section id="c-api-wishes">
<h2><a class="toc-backref" href="#c-api-wishes" role="doc-backlink">C API wishes</a></h2>
<ul>
<li>Add C API functions to help Windows users who are building embedded
applications where the FILE * structure does not match the FILE *
the interpreter was compiled with.<p><a class="reference external" href="https://bugs.python.org/issue210821">https://bugs.python.org/issue210821</a></p>
<p>See this bug report for a specific suggestion that will allow a
Borland C++ builder application to interact with a python.dll build
with MSVC.</p>
</li>
</ul>
</section>
<section id="tools">
<h2><a class="toc-backref" href="#tools" role="doc-backlink">Tools</a></h2>
<ul>
<li>Python could use a GUI builder.<p><a class="reference external" href="https://bugs.python.org/issue210820">https://bugs.python.org/issue210820</a></p>
</li>
</ul>
</section>
<section id="building-and-installing">
<h2><a class="toc-backref" href="#building-and-installing" role="doc-backlink">Building and Installing</a></h2>
<ul>
<li>Modules/makesetup should make sure the config.c file it generates
from the various Setup files, is valid C. It currently accepts
module names with characters that are not allowable in Python or C
identifiers.<p><a class="reference external" href="https://bugs.python.org/issue216326">https://bugs.python.org/issue216326</a></p>
</li>
<li>Building from source should not attempt to overwrite the
Include/graminit.h and Parser/graminit.c files, at least for people
downloading a source release rather than working from Subversion or
snapshots. Some people find this a problem in unusual build
environments.<p><a class="reference external" href="https://bugs.python.org/issue219221">https://bugs.python.org/issue219221</a></p>
</li>
<li>The configure script has probably grown a bit crufty with age and
may not track autoconfs more recent features very well. It should
be looked at and possibly cleaned up.<p><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2004-January/041790.html">https://mail.python.org/pipermail/python-dev/2004-January/041790.html</a></p>
</li>
<li>Make Python compliant to the FHS (the Filesystem Hierarchy
Standard)<p><a class="reference external" href="http://bugs.python.org/issue588756">http://bugs.python.org/issue588756</a></p>
</li>
</ul>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0042.rst">https://github.com/python/peps/blob/main/peps/pep-0042.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0042.rst">2024-04-14 20:08:31 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#core-language-builtins">Core Language / Builtins</a></li>
<li><a class="reference internal" href="#standard-library">Standard Library</a></li>
<li><a class="reference internal" href="#c-api-wishes">C API wishes</a></li>
<li><a class="reference internal" href="#tools">Tools</a></li>
<li><a class="reference internal" href="#building-and-installing">Building and Installing</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0042.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

1314
pep-0100/index.html Normal file

File diff suppressed because it is too large Load Diff

919
pep-0101/index.html Normal file
View File

@ -0,0 +1,919 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 101 Doing Python Releases 101 | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0101/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 101 Doing Python Releases 101 | peps.python.org'>
<meta property="og:description" content="Making a Python release is a thrilling and crazy process. Youve heard the expression “herding cats”? Imagine trying to also saddle those purring little creatures up, and ride them into town, with some of their buddies firmly attached to your bare bac...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0101/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Making a Python release is a thrilling and crazy process. Youve heard the expression “herding cats”? Imagine trying to also saddle those purring little creatures up, and ride them into town, with some of their buddies firmly attached to your bare bac...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 101</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 101 Doing Python Releases 101</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;, Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Currently valid informational guidance, or an in-use process">Active</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">22-Aug-2001</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
<dt class="field-even">Replaces<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../pep-0102/">102</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#things-you-ll-need">Things Youll Need</a></li>
<li><a class="reference internal" href="#types-of-releases">Types of Releases</a></li>
<li><a class="reference internal" href="#how-to-make-a-release">How To Make A Release</a></li>
<li><a class="reference internal" href="#what-next">What Next?</a></li>
<li><a class="reference internal" href="#moving-to-end-of-life">Moving to End-of-life</a></li>
<li><a class="reference internal" href="#windows-notes">Windows Notes</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Making a Python release is a thrilling and crazy process. Youve heard
the expression “herding cats”? Imagine trying to also saddle those
purring little creatures up, and ride them into town, with some of their
buddies firmly attached to your bare back, anchored by newly sharpened
claws. At least theyre cute, you remind yourself.</p>
<p>Actually, no, thats a slight exaggeration 😉 The Python release
process has steadily improved over the years and now, with the help of our
amazing community, is really not too difficult. This PEP attempts to
collect, in one place, all the steps needed to make a Python release.
Most of the steps are now automated or guided by automation, so manually
following this list is no longer necessary.</p>
</section>
<section id="things-you-ll-need">
<h2><a class="toc-backref" href="#things-you-ll-need" role="doc-backlink">Things Youll Need</a></h2>
<p>As a release manager there are a lot of resources youll need to access.
Heres a hopefully-complete list.</p>
<ul>
<li>A GPG key.<p>Python releases are digitally signed with GPG; youll need a key,
which hopefully will be on the “web of trust” with at least one of
the other release managers.</p>
</li>
<li>A bunch of software:<ul class="simple">
<li>A checkout of the <a class="reference external" href="https://github.com/python/release-tools">python/release-tools</a> repo.
It contains a <a class="reference external" href="https://github.com/python/release-tools/blob/master/requirements.txt">requirements.txt</a>
file that you need to install
dependencies from first. Afterwards, you can fire up scripts in the
repo, covered later in this PEP.</li>
<li><a class="reference external" href="https://github.com/python/blurb">blurb</a>, the
<a class="reference external" href="https://github.com/python/cpython/tree/main/Misc/NEWS.d">Misc/NEWS</a>
management tool. You can pip install it.</li>
</ul>
</li>
<li>Access to servers where you will upload files:<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">downloads.nyc1.psf.io</span></code>, the server that hosts download files; and</li>
<li><code class="docutils literal notranslate"><span class="pre">docs.nyc1.psf.io</span></code>, the server that hosts the documentation.</li>
</ul>
</li>
<li>Administrator access to <a class="reference external" href="https://github.com/python/cpython">python/cpython</a>.</li>
<li>An administrator account on <a class="reference external" href="https://www.python.org">www.python.org</a>, including an “API key”.</li>
<li>Write access to the <a class="reference external" href="https://github.com/python/peps">python/peps</a> repository.<p>If youre reading this, you probably already have thisthe first
task of any release manager is to draft the release schedule. But
in case you just signed up… sucker! I mean, uh, congratulations!</p>
</li>
<li>Posting access to <a class="reference external" href="https://blog.python.org">blog.python.org</a>, a Blogger-hosted weblog.
The RSS feed from this blog is used for the Python News section
on <a class="reference external" href="https://www.python.org">www.python.org</a>.</li>
<li>A subscription to the super secret release manager mailing list, which may
or may not be called <code class="docutils literal notranslate"><span class="pre">python-cabal</span></code>. Bug Barry about this.</li>
<li>A <code class="docutils literal notranslate"><span class="pre">&#64;python.org</span></code> email address that you will use to sign your releases
with. Ask <code class="docutils literal notranslate"><span class="pre">postmaster&#64;</span></code> for an address; you can either get a full
account, or a redirecting alias + SMTP credentials to send email from
this address that looks legit to major email providers.</li>
<li>Be added to the <a class="reference external" href="https://www.python.org/dev/security/">Python Security Response Team</a>.</li>
</ul>
</section>
<section id="types-of-releases">
<h2><a class="toc-backref" href="#types-of-releases" role="doc-backlink">Types of Releases</a></h2>
<p>There are several types of releases you will need to make. These include:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">alpha</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">begin</span> <span class="pre">beta</span></code>, also known as <code class="docutils literal notranslate"><span class="pre">beta</span> <span class="pre">1</span></code>, also known as <code class="docutils literal notranslate"><span class="pre">new</span> <span class="pre">branch</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">beta</span> <span class="pre">2+</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">release</span> <span class="pre">candidate</span> <span class="pre">1</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">release</span> <span class="pre">candidate</span> <span class="pre">2+</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">final</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">new</span> <span class="pre">branch</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">begin</span> <span class="pre">bugfix</span> <span class="pre">mode</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">begin</span> <span class="pre">security-only</span> <span class="pre">mode</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">end-of-life</span></code></li>
</ul>
<p>Some of these release types actually involve more than
one release branch. In particular, a <strong>new branch</strong> is that point in the
release cycle when a new feature release cycle begins. Under the current
organization of the CPython Git repository, the <em>main</em> branch is always
the target for new features. At some point in the release cycle of the
next feature release, a <strong>new branch</strong> release is made which creates a
new separate branch for stabilization and later maintenance of the
current in-progress feature release (<code class="docutils literal notranslate"><span class="pre">3.n.0</span></code>) and the <em>main</em> branch is modified
to build a new version (which will eventually be released as <code class="docutils literal notranslate"><span class="pre">3.n+1.0</span></code>).
While the <strong>new branch</strong> release step could occur at one of several points
in the release cycle, current practice is for it to occur at feature code
cutoff for the release which is scheduled for the first beta release.</p>
<p>In the descriptions that follow, steps specific to release types are
labeled accordingly, for now, <strong>new branch</strong> and <strong>final</strong>.</p>
</section>
<section id="how-to-make-a-release">
<h2><a class="toc-backref" href="#how-to-make-a-release" role="doc-backlink">How To Make A Release</a></h2>
<p>Here are the steps taken to make a Python release. Some steps are more
fuzzy than others because theres little that can be automated (e.g.
writing the NEWS entries). Where a step is usually performed by An
Expert, the role of that expert is given. Otherwise, assume the step is
done by the Release Manager (RM), the designated person performing the
release. The roles and their current experts are:</p>
<ul class="simple">
<li>RM = Release Manager<ul>
<li>Hugo van Kemenade &lt;<a class="reference external" href="mailto:hugo&#37;&#52;&#48;python&#46;org">hugo<span>&#64;</span>python<span>&#46;</span>org</a>&gt; (FI)</li>
<li>Thomas Wouters &lt;<a class="reference external" href="mailto:thomas&#37;&#52;&#48;python&#46;org">thomas<span>&#64;</span>python<span>&#46;</span>org</a>&gt; (NL)</li>
<li>Pablo Galindo Salgado &lt;<a class="reference external" href="mailto:pablogsal&#37;&#52;&#48;python&#46;org">pablogsal<span>&#64;</span>python<span>&#46;</span>org</a>&gt; (UK)</li>
<li>Łukasz Langa &lt;<a class="reference external" href="mailto:lukasz&#37;&#52;&#48;python&#46;org">lukasz<span>&#64;</span>python<span>&#46;</span>org</a>&gt; (PL)</li>
</ul>
</li>
<li>WE = Windows - Steve Dower &lt;<a class="reference external" href="mailto:steve&#46;dower&#37;&#52;&#48;python&#46;org">steve<span>&#46;</span>dower<span>&#64;</span>python<span>&#46;</span>org</a>&gt;</li>
<li>ME = Mac - Ned Deily &lt;<a class="reference external" href="mailto:nad&#37;&#52;&#48;python&#46;org">nad<span>&#64;</span>python<span>&#46;</span>org</a>&gt; (US)</li>
<li>DE = Docs - Julien Palard &lt;<a class="reference external" href="mailto:julien&#37;&#52;&#48;python&#46;org">julien<span>&#64;</span>python<span>&#46;</span>org</a>&gt; (Central Europe)</li>
</ul>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>It is highly recommended that the RM contact the Experts the day
before the release. Because the world is round and everyone lives
in different timezones, the RM must ensure that the release tag is
created in enough time for the Experts to cut binary releases.</p>
<p>You should not make the release public (by updating the website and
sending announcements) before all experts have updated their bits.
In rare cases where the expert for Windows or Mac is MIA, you may add
a message “(Platform) binaries will be provided shortly” and proceed.</p>
</div>
<p>As much as possible, the release steps are automated and guided by the
release script, which is available in a separate repository:
<a class="reference external" href="https://github.com/python/release-tools">python/release-tools</a>.</p>
<p>We use the following conventions in the examples below. Where a release
number is given, it is of the form <code class="docutils literal notranslate"><span class="pre">3.X.YaN</span></code>, e.g. 3.13.0a3 for Python 3.13.0
alpha 3, where “a” == alpha, “b” == beta, “rc” == release candidate.</p>
<p>Release tags are named <code class="docutils literal notranslate"><span class="pre">v3.X.YaN</span></code>. The branch name for minor release
maintenance branches is <code class="docutils literal notranslate"><span class="pre">3.X</span></code>.</p>
<p>This helps by performing several automatic editing steps, and guides you
to perform some manual editing steps.</p>
<ul>
<li>Log into Discord and join the Python Core Devs server. Ask Thomas
or Łukasz for an invite.<p>You probably need to coordinate with other people around the world.
This communication channel is where weve arranged to meet.</p>
</li>
<li>Check to see if there are any showstopper bugs.<p>Go to <a class="reference external" href="https://github.com/python/cpython/issues">https://github.com/python/cpython/issues</a> and look for any open
bugs that can block this release. Youre looking at two relevant labels:</p>
<dl class="simple">
<dt><a class="reference external" href="https://github.com/python/cpython/labels/release-blocker">release-blocker</a></dt><dd>Stops the release dead in its tracks. You may not
make any release with any open release blocker bugs.</dd>
<dt><a class="reference external" href="https://github.com/python/cpython/labels/deferred-blocker">deferred-blocker</a></dt><dd>Doesnt block this release, but it will block a
future release. You may not make a final or
candidate release with any open deferred blocker
bugs.</dd>
</dl>
<p>Review the release blockers and either resolve them, bump them down to
deferred, or stop the release and ask for community assistance. If
youre making a final or candidate release, do the same with any open
deferred.</p>
</li>
<li>Check the stable buildbots.<p>Go to <a class="reference external" href="https://buildbot.python.org/all/#/release_status">https://buildbot.python.org/all/#/release_status</a></p>
<p>Look at the buildbots for the release
youre making. Ignore any that are offline (or inform the community so
they can be restarted). If what remains are (mostly) green buildbots,
youre good to go. If you have non-offline red buildbots, you may want
to hold up the release until they are fixed. Review the problems and
use your judgement, taking into account whether you are making an alpha,
beta, or final release.</p>
</li>
<li>Make a release clone.<p>On a fork of the CPython repository on GitHub, create a release branch
within it (called the “release clone” from now on). You can use the same
GitHub fork you use for CPython development. Using the standard setup
recommended in the <a class="reference external" href="https://devguide.python.org/">Python Developers Guide</a>,
your fork would be referred
to as <code class="docutils literal notranslate"><span class="pre">origin</span></code> and the standard CPython repo as <code class="docutils literal notranslate"><span class="pre">upstream</span></code>. You will
use the branch on your fork to do the release engineering work, including
tagging the release, and you will use it to share with the other experts
for making the binaries.</p>
<p>For a <strong>final</strong> or <strong>release candidate 2+</strong> release, if you are going
to cherry-pick a subset of changes for the next rc or final from all those
merged since the last rc, you should create a release
engineering branch starting from the most recent release candidate tag,
i.e. <code class="docutils literal notranslate"><span class="pre">v3.8.0rc1</span></code>. You will then cherry-pick changes from the standard
release branch as necessary into the release engineering branch and
then proceed as usual. If you are going to take all of the changes
since the previous rc, you can proceed as normal.</p>
</li>
<li>Make sure the current branch of your release clone is the branch you
want to release from (<code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">status</span></code>).</li>
<li>Run <code class="docutils literal notranslate"><span class="pre">blurb</span> <span class="pre">release</span> <span class="pre">&lt;version&gt;</span></code> specifying the version number
(e.g. <code class="docutils literal notranslate"><span class="pre">blurb</span> <span class="pre">release</span> <span class="pre">3.4.7rc1</span></code>). This merges all the recent news
blurbs into a single file marked with this releases version number.</li>
<li>Regenerate <code class="docutils literal notranslate"><span class="pre">Lib/pydoc-topics.py</span></code>.<p>While still in the <code class="docutils literal notranslate"><span class="pre">Doc</span></code> directory, run:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>make<span class="w"> </span>pydoc-topics
cp<span class="w"> </span>build/pydoc-topics/topics.py<span class="w"> </span>../Lib/pydoc_data/topics.py
</pre></div>
</div>
</li>
<li>Commit your changes to <code class="docutils literal notranslate"><span class="pre">pydoc_topics.py</span></code>
(and any fixes you made in the docs).</li>
<li>Consider running <code class="docutils literal notranslate"><span class="pre">autoconf</span></code> using the currently accepted standard version
in case <code class="docutils literal notranslate"><span class="pre">configure</span></code> or other Autoconf-generated files were last
committed with a newer or older version and may contain spurious or
harmful differences. Currently, Autoconf 2.71 is our de facto standard.
if there are differences, commit them.</li>
<li>Make sure the <code class="docutils literal notranslate"><span class="pre">SOURCE_URI</span></code> in <code class="docutils literal notranslate"><span class="pre">Doc/tools/extensions/pyspecific.py</span></code>
points to the right branch in the Git repository (<code class="docutils literal notranslate"><span class="pre">main</span></code> or <code class="docutils literal notranslate"><span class="pre">3.X</span></code>).
For a <strong>new branch</strong> release, change the branch in the file from <code class="docutils literal notranslate"><span class="pre">main</span></code>
to the new release branch you are about to create (<code class="docutils literal notranslate"><span class="pre">3.X</span></code>).</li>
<li>Bump version numbers via the release script:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>.../release-tools/release.py<span class="w"> </span>--bump<span class="w"> </span><span class="m">3</span>.X.YaN
</pre></div>
</div>
<p>Reminder: <code class="docutils literal notranslate"><span class="pre">X</span></code>, <code class="docutils literal notranslate"><span class="pre">Y</span></code>, and <code class="docutils literal notranslate"><span class="pre">N</span></code> should be integers.
<code class="docutils literal notranslate"><span class="pre">a</span></code> should be one of <code class="docutils literal notranslate"><span class="pre">a</span></code>, <code class="docutils literal notranslate"><span class="pre">b</span></code>, or <code class="docutils literal notranslate"><span class="pre">rc</span></code> (e.g. <code class="docutils literal notranslate"><span class="pre">3.4.3rc1</span></code>).
For <strong>final</strong> releases omit the <code class="docutils literal notranslate"><span class="pre">aN</span></code> (<code class="docutils literal notranslate"><span class="pre">3.4.3</span></code>). For the first
release of a new version <code class="docutils literal notranslate"><span class="pre">Y</span></code> should be <code class="docutils literal notranslate"><span class="pre">0</span></code> (<code class="docutils literal notranslate"><span class="pre">3.6.0</span></code>).</p>
<p>This automates updating various release numbers, but you will have to
modify a few files manually. If your <code class="docutils literal notranslate"><span class="pre">$EDITOR</span></code> environment variable is
set up correctly, <code class="docutils literal notranslate"><span class="pre">release.py</span></code> will pop up editor windows with the files
you need to edit.</p>
<p>Review the blurb-generated <code class="docutils literal notranslate"><span class="pre">Misc/NEWS</span></code> file and edit as necessary.</p>
</li>
<li>Make sure all changes have been committed. (<code class="docutils literal notranslate"><span class="pre">release.py</span> <span class="pre">--bump</span></code>
doesnt check in its changes for you.)</li>
<li>Check the years on the copyright notice. If the last release
was some time last year, add the current year to the copyright
notice in several places:<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">README</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">LICENSE</span></code> (make sure to change on <code class="docutils literal notranslate"><span class="pre">main</span></code> and the branch)</li>
<li><code class="docutils literal notranslate"><span class="pre">Python/getcopyright.c</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Doc/copyright.rst</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Doc/license.rst</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">PC/python_ver_rc.h</span></code> sets up the DLL version resource for Windows
(displayed when you right-click on the DLL and select
Properties). This isnt a C include file, its a Windows
“resource file” include file.</li>
</ul>
</li>
<li>For a <strong>final</strong> major release, edit the first paragraph of
<code class="docutils literal notranslate"><span class="pre">Doc/whatsnew/3.X.rst</span></code> to include the actual release date; e.g. “Python
2.5 was released on August 1, 2003.” Theres no need to edit this for
alpha or beta releases.</li>
<li>Do a <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">status</span></code> in this directory.<p>You should not see any files, i.e., you better not have any uncommitted
changes in your working directory.</p>
</li>
<li>Tag the release for <code class="docutils literal notranslate"><span class="pre">3.X.YaN</span></code>:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>.../release-tools/release.py<span class="w"> </span>--tag<span class="w"> </span><span class="m">3</span>.X.YaN
</pre></div>
</div>
<p>This executes a <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">tag</span></code> command with the <code class="docutils literal notranslate"><span class="pre">-s</span></code> option so that the
release tag in the repo is signed with your GPG key. When prompted
choose the private key you use for signing release tarballs etc.</p>
</li>
<li>For <strong>begin security-only mode</strong> and <strong>end-of-life</strong> releases, review the
two files and update the versions accordingly in all active branches.</li>
<li>Time to build the source tarball. Use the release script to create
the source gzip and xz tarballs,
documentation tar and zip files, and GPG signature files:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>.../release-tools/release.py<span class="w"> </span>--export<span class="w"> </span><span class="m">3</span>.X.YaN
</pre></div>
</div>
<p>This can take a while for <strong>final</strong> releases, and it will leave all the
tarballs and signatures in a subdirectory called <code class="docutils literal notranslate"><span class="pre">3.X.YaN/src</span></code>, and the
built docs in <code class="docutils literal notranslate"><span class="pre">3.X.YaN/docs</span></code> (for <strong>final</strong> releases).</p>
<p>Note that the script will sign your release with Sigstore. Use
your <strong>&#64;python.org</strong> email address for this. See here for more information:
<a class="reference external" href="https://www.python.org/download/sigstore/">https://www.python.org/download/sigstore/</a>.</p>
</li>
<li>Now you want to perform the very important step of checking the
tarball you just created, to make sure a completely clean,
virgin build passes the regression test. Here are the best
steps to take:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="nb">cd</span><span class="w"> </span>/tmp
tar<span class="w"> </span>xvf<span class="w"> </span>/path/to/your/release/clone/&lt;version&gt;//Python-3.2rc2.tgz
<span class="nb">cd</span><span class="w"> </span>Python-3.2rc2
ls
<span class="c1"># (Do things look reasonable?)</span>
ls<span class="w"> </span>Lib
<span class="c1"># (Are there stray .pyc files?)</span>
./configure
<span class="c1"># (Loads of configure output)</span>
make<span class="w"> </span><span class="nb">test</span>
<span class="c1"># (Do all the expected tests pass?)</span>
</pre></div>
</div>
<p>If youre feeling lucky and have some time to kill, or if you are making
a release candidate or <strong>final</strong> release, run the full test suite:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>make<span class="w"> </span>buildbottest
</pre></div>
</div>
<p>If the tests pass, then you can feel good that the tarball is
fine. If some of the tests fail, or anything else about the
freshly unpacked directory looks weird, you better stop now and
figure out what the problem is.</p>
</li>
<li>Push your commits to the remote release branch in your GitHub fork:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="c1"># Do a dry run first.</span>
git<span class="w"> </span>push<span class="w"> </span>--dry-run<span class="w"> </span>--tags<span class="w"> </span>origin
<span class="c1"># Make sure you are pushing to your GitHub fork,</span>
<span class="c1"># *not* to the main python/cpython repo!</span>
git<span class="w"> </span>push<span class="w"> </span>--tags<span class="w"> </span>origin
</pre></div>
</div>
</li>
<li>Notify the experts that they can start building binaries.</li>
</ul>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p><strong>STOP</strong>: at this point you must receive the “green light” from other experts
in order to create the release. There are things you can do while you wait
though, so keep reading until you hit the next STOP.</p>
</div>
<ul>
<li>The WE generates and publishes the Windows files using the Azure
Pipelines build scripts in <code class="docutils literal notranslate"><span class="pre">.azure-pipelines/windows-release/</span></code>,
currently set up at <a class="reference external" href="https://dev.azure.com/Python/cpython/_build?definitionId=21">https://dev.azure.com/Python/cpython/_build?definitionId=21</a>.<p>The build process runs in multiple stages, with each stages output being
available as a downloadable artifact. The stages are:</p>
<ul class="simple">
<li>Compile all variants of binaries (32-bit, 64-bit, debug/release),
including running profile-guided optimization.</li>
<li>Compile the HTML Help file containing the Python documentation.</li>
<li>Codesign all the binaries with the PSFs certificate.</li>
<li>Create packages for python.org, nuget.org, the embeddable distro and
the Windows Store.</li>
<li>Perform basic verification of the installers.</li>
<li>Upload packages to python.org and nuget.org, purge download caches and
run a test download.</li>
</ul>
<p>After the uploads are complete, the WE copies the generated hashes from
the build logs and emails them to the RM. The Windows Store packages are
uploaded manually to <a class="reference external" href="https://partner.microsoft.com/dashboard/home">https://partner.microsoft.com/dashboard/home</a> by the
WE.</p>
</li>
<li>The ME builds Mac installer packages and uploads them to
downloads.nyc1.psf.io together with GPG signature files.</li>
<li><code class="docutils literal notranslate"><span class="pre">scp</span></code> or <code class="docutils literal notranslate"><span class="pre">rsync</span></code> all the files built by <code class="docutils literal notranslate"><span class="pre">release.py</span> <span class="pre">--export</span></code>
to your home directory on <code class="docutils literal notranslate"><span class="pre">downloads.nyc1.psf.io</span></code>.<p>While youre waiting for the files to finish uploading, you can continue
on with the remaining tasks. You can also ask folks on Discord
and/or <a class="reference external" href="https://discuss.python.org">discuss.python.org</a> to download the files as they finish uploading
so that they can test them on their platforms as well.</p>
</li>
<li>Now you need to go to <code class="docutils literal notranslate"><span class="pre">downloads.nyc1.psf.io</span></code> and move all the files in place
over there. Our policy is that every Python version gets its own
directory, but each directory contains all releases of that version.<ul>
<li>On <code class="docutils literal notranslate"><span class="pre">downloads.nyc1.psf.io</span></code>, <code class="docutils literal notranslate"><span class="pre">cd</span> <span class="pre">/srv/www.python.org/ftp/python/3.X.Y</span></code>
creating it if necessary. Make sure it is owned by group <code class="docutils literal notranslate"><span class="pre">downloads</span></code>
and group-writable.</li>
<li>Move the release <code class="docutils literal notranslate"><span class="pre">.tgz</span></code>, and <code class="docutils literal notranslate"><span class="pre">.tar.xz</span></code> files into place, as well as the
<code class="docutils literal notranslate"><span class="pre">.asc</span></code> GPG signature files. The Win/Mac binaries are usually put there
by the experts themselves.<p>Make sure they are world readable. They should also be group
writable, and group-owned by <code class="docutils literal notranslate"><span class="pre">downloads</span></code>.</p>
</li>
<li>Use <code class="docutils literal notranslate"><span class="pre">gpg</span> <span class="pre">--verify</span></code> to make sure they got uploaded intact.</li>
<li>If this is a <strong>final</strong> or rc release: Move the doc zips and tarballs to
<code class="docutils literal notranslate"><span class="pre">/srv/www.python.org/ftp/python/doc/3.X.Y[rcA]</span></code>, creating the directory
if necessary, and adapt the “current” symlink in <code class="docutils literal notranslate"><span class="pre">.../doc</span></code> to point to
that directory. Note though that if youre releasing a maintenance
release for an older version, dont change the current link.</li>
<li>If this is a <strong>final</strong> or rc release (even a maintenance release), also
unpack the HTML docs to <code class="docutils literal notranslate"><span class="pre">/srv/docs.python.org/release/3.X.Y[rcA]</span></code> on
<code class="docutils literal notranslate"><span class="pre">docs.nyc1.psf.io</span></code>. Make sure the files are in group <code class="docutils literal notranslate"><span class="pre">docs</span></code> and are
group-writeable.</li>
<li>Let the DE check if the docs are built and work all right.</li>
<li>Note both the documentation and downloads are behind a caching CDN. If
you change archives after downloading them through the website, youll
need to purge the stale data in the CDN like this:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>curl<span class="w"> </span>-X<span class="w"> </span>PURGE<span class="w"> </span>https://www.python.org/ftp/python/3.12.0/Python-3.12.0.tar.xz
</pre></div>
</div>
<p>You should always purge the cache of the directory listing as people
use that to browse the release files:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>curl<span class="w"> </span>-X<span class="w"> </span>PURGE<span class="w"> </span>https://www.python.org/ftp/python/3.12.0/
</pre></div>
</div>
</li>
</ul>
</li>
<li>For the extra paranoid, do a completely clean test of the release.
This includes downloading the tarball from <a class="reference external" href="https://www.python.org">www.python.org</a>.<p>Make sure the md5 checksums match. Then unpack the tarball,
and do a clean make test:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>make<span class="w"> </span>distclean
./configure
make<span class="w"> </span><span class="nb">test</span>
</pre></div>
</div>
<p>To ensure that the regression test suite passes. If not, you
screwed up somewhere!</p>
</li>
</ul>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p><strong>STOP</strong> and confirm:</p>
<ul class="simple">
<li>Have you gotten the green light from the WE?</li>
<li>Have you gotten the green light from the ME?</li>
<li>Have you gotten the green light from the DE?</li>
</ul>
</div>
<p>If green, its time to merge the release engineering branch back into
the main repo.</p>
<ul>
<li>In order to push your changes to GitHub, youll have to temporarily
disable branch protection for administrators. Go to the
<code class="docutils literal notranslate"><span class="pre">Settings</span> <span class="pre">|</span> <span class="pre">Branches</span></code> page:<p><a class="reference external" href="https://github.com/python/cpython/settings/branches">https://github.com/python/cpython/settings/branches</a></p>
<p>“Edit” the settings for the branch youre releasing on.
This will load the settings page for that branch.
Uncheck the “Include administrators” box and press the
“Save changes” button at the bottom.</p>
</li>
<li>Merge your release clone into the main development repo:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="c1"># Pristine copy of the upstream repo branch</span>
git<span class="w"> </span>clone<span class="w"> </span>git@github.com:python/cpython.git<span class="w"> </span>merge
<span class="nb">cd</span><span class="w"> </span>merge
<span class="c1"># Checkout the correct branch:</span>
<span class="c1"># 1. For feature pre-releases up to and including a</span>
<span class="c1"># **new branch** release, i.e. alphas and first beta</span>
<span class="c1"># do a checkout of the main branch</span>
git<span class="w"> </span>checkout<span class="w"> </span>main
<span class="c1"># 2. Else, for all other releases, checkout the</span>
<span class="c1"># appropriate release branch.</span>
git<span class="w"> </span>checkout<span class="w"> </span><span class="m">3</span>.X
<span class="c1"># Fetch the newly created and signed tag from your clone repo</span>
git<span class="w"> </span>fetch<span class="w"> </span>--tags<span class="w"> </span>git@github.com:your-github-id/cpython.git<span class="w"> </span>v3.X.YaN
<span class="c1"># Merge the temporary release engineering branch back into</span>
git<span class="w"> </span>merge<span class="w"> </span>--no-squash<span class="w"> </span>v3.X.YaN
git<span class="w"> </span>commit<span class="w"> </span>-m<span class="w"> </span><span class="s1">&#39;Merge release engineering branch&#39;</span>
</pre></div>
</div>
</li>
<li>If this is a <strong>new branch</strong> release, i.e. first beta,
now create the new release branch:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>git<span class="w"> </span>checkout<span class="w"> </span>-b<span class="w"> </span><span class="m">3</span>.X
</pre></div>
</div>
<p>Do any steps needed to setup the new release branch, including:</p>
<ul class="simple">
<li>In <code class="docutils literal notranslate"><span class="pre">README.rst</span></code>, change all references from <code class="docutils literal notranslate"><span class="pre">main</span></code> to
the new branch, in particular, GitHub repo URLs.</li>
</ul>
</li>
<li>For <em>all</em> releases, do the guided post-release steps with the
release script:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>.../release-tools/release.py<span class="w"> </span>--done<span class="w"> </span><span class="m">3</span>.X.YaN
</pre></div>
</div>
</li>
<li>For a <strong>final</strong> or <strong>release candidate 2+</strong> release, you may need to
do some post-merge cleanup. Check the top-level <code class="docutils literal notranslate"><span class="pre">README.rst</span></code>
and <code class="docutils literal notranslate"><span class="pre">include/patchlevel.h</span></code> files to ensure they now reflect
the desired post-release values for on-going development.
The patchlevel should be the release tag with a <code class="docutils literal notranslate"><span class="pre">+</span></code>.
Also, if you cherry-picked changes from the standard release
branch into the release engineering branch for this release,
you will now need to manually remove each blurb entry from
the <code class="docutils literal notranslate"><span class="pre">Misc/NEWS.d/next</span></code> directory that was cherry-picked
into the release you are working on since that blurb entry
is now captured in the merged <code class="docutils literal notranslate"><span class="pre">x.y.z.rst</span></code> file for the new
release. Otherwise, the blurb entry will appear twice in
the <code class="docutils literal notranslate"><span class="pre">changelog.html</span></code> file, once under <code class="docutils literal notranslate"><span class="pre">Python</span> <span class="pre">next</span></code> and again
under <code class="docutils literal notranslate"><span class="pre">x.y.z</span></code>.</li>
<li>Review and commit these changes:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>git<span class="w"> </span>commit<span class="w"> </span>-m<span class="w"> </span><span class="s1">&#39;Post release updates&#39;</span>
</pre></div>
</div>
</li>
<li>If this is a <strong>new branch</strong> release (e.g. the first beta),
update the <code class="docutils literal notranslate"><span class="pre">main</span></code> branch to start development for the
following feature release. When finished, the <code class="docutils literal notranslate"><span class="pre">main</span></code>
branch will now build Python <code class="docutils literal notranslate"><span class="pre">X.Y+1</span></code>.<ul>
<li>First, set <code class="docutils literal notranslate"><span class="pre">main</span></code> up to be the next release, i.e. X.Y+1.a0:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>git<span class="w"> </span>checkout<span class="w"> </span>main
.../release-tools/release.py<span class="w"> </span>--bump<span class="w"> </span><span class="m">3</span>.9.0a0
</pre></div>
</div>
</li>
<li>Edit all version references in <code class="docutils literal notranslate"><span class="pre">README.rst</span></code></li>
<li>Move any historical “whats new” entries from <code class="docutils literal notranslate"><span class="pre">Misc/NEWS</span></code> to
<code class="docutils literal notranslate"><span class="pre">Misc/HISTORY</span></code>.</li>
<li>Edit <code class="docutils literal notranslate"><span class="pre">Doc/tutorial/interpreter.rst</span></code> (two references to [Pp]ython3x,
one to Python 3.x, also make the date in the banner consistent).</li>
<li>Edit <code class="docutils literal notranslate"><span class="pre">Doc/tutorial/stdlib.rst</span></code> and <code class="docutils literal notranslate"><span class="pre">Doc/tutorial/stdlib2.rst</span></code>, which
have each one reference to [Pp]ython3x.</li>
<li>Add a new <code class="docutils literal notranslate"><span class="pre">whatsnew/3.x.rst</span></code> file (with the comment near the top
and the toplevel sections copied from the previous file) and
add it to the toctree in <code class="docutils literal notranslate"><span class="pre">whatsnew/index.rst</span></code>. But beware that
the initial <code class="docutils literal notranslate"><span class="pre">whatsnew/3.x.rst</span></code> checkin from previous releases
may be incorrect due to the initial midstream change to <code class="docutils literal notranslate"><span class="pre">blurb</span></code>
that propagates from release to release! Help break the cycle: if
necessary make the following change:<div class="highlight-diff notranslate"><div class="highlight"><pre><span></span><span class="gd">-For full details, see the :source:`Misc/NEWS` file.</span>
<span class="gi">+For full details, see the :ref:`changelog &lt;changelog&gt;`.</span>
</pre></div>
</div>
</li>
<li>Update the version number in <code class="docutils literal notranslate"><span class="pre">configure.ac</span></code> and re-run <code class="docutils literal notranslate"><span class="pre">autoconf</span></code>.</li>
<li>Make sure the <code class="docutils literal notranslate"><span class="pre">SOURCE_URI</span></code> in <code class="docutils literal notranslate"><span class="pre">Doc/tools/extensions/pyspecific.py</span></code>
points to <code class="docutils literal notranslate"><span class="pre">main</span></code>.</li>
<li>Update the version numbers for the Windows builds
which have references to <code class="docutils literal notranslate"><span class="pre">python38</span></code>:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>ls<span class="w"> </span>PC/pyconfig.h.in<span class="w"> </span>PCbuild/rt.bat<span class="w"> </span><span class="p">|</span><span class="w"> </span>xargs<span class="w"> </span>sed<span class="w"> </span>-i<span class="w"> </span><span class="s1">&#39;s/python3\(\.\?\)[0-9]\+/python3\19/g&#39;</span>
</pre></div>
</div>
</li>
<li>Commit these changes to the main branch:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>git<span class="w"> </span>status
git<span class="w"> </span>add<span class="w"> </span>...
git<span class="w"> </span>commit<span class="w"> </span>-m<span class="w"> </span><span class="s1">&#39;Bump to 3.9.0a0&#39;</span>
</pre></div>
</div>
</li>
</ul>
</li>
<li>Do another <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">status</span></code> in this directory.<p>You should not see any files, i.e., you better not have any uncommitted
changes in your working directory.</p>
</li>
<li>Commit and push to the main repo:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="c1"># Do a dry run first.</span>
<span class="c1"># For feature pre-releases prior to a **new branch** release,</span>
<span class="c1"># i.e. a feature alpha release:</span>
git<span class="w"> </span>push<span class="w"> </span>--dry-run<span class="w"> </span>--tags<span class="w"> </span>git@github.com:python/cpython.git<span class="w"> </span>main
<span class="c1"># If it looks OK, take the plunge. There&#39;s no going back!</span>
git<span class="w"> </span>push<span class="w"> </span>--tags<span class="w"> </span>git@github.com:python/cpython.git<span class="w"> </span>main
<span class="c1"># For a **new branch** release, i.e. first beta:</span>
git<span class="w"> </span>push<span class="w"> </span>--dry-run<span class="w"> </span>--tags<span class="w"> </span>git@github.com:python/cpython.git<span class="w"> </span><span class="m">3</span>.X
git<span class="w"> </span>push<span class="w"> </span>--dry-run<span class="w"> </span>--tags<span class="w"> </span>git@github.com:python/cpython.git<span class="w"> </span>main
<span class="c1"># If it looks OK, take the plunge. There&#39;s no going back!</span>
git<span class="w"> </span>push<span class="w"> </span>--tags<span class="w"> </span>git@github.com:python/cpython.git<span class="w"> </span><span class="m">3</span>.X
git<span class="w"> </span>push<span class="w"> </span>--tags<span class="w"> </span>git@github.com:python/cpython.git<span class="w"> </span>main
<span class="c1"># For all other releases:</span>
git<span class="w"> </span>push<span class="w"> </span>--dry-run<span class="w"> </span>--tags<span class="w"> </span>git@github.com:python/cpython.git<span class="w"> </span><span class="m">3</span>.X
<span class="c1"># If it looks OK, take the plunge. There&#39;s no going back!</span>
git<span class="w"> </span>push<span class="w"> </span>--tags<span class="w"> </span>git@github.com:python/cpython.git<span class="w"> </span><span class="m">3</span>.X
</pre></div>
</div>
</li>
<li>If this is a <strong>new branch</strong> release, add a <code class="docutils literal notranslate"><span class="pre">Branch</span> <span class="pre">protection</span> <span class="pre">rule</span></code>
for the newly created branch (3.X). Look at the values for the previous
release branch (3.X-1) and use them as a template.
<a class="reference external" href="https://github.com/python/cpython/settings/branches">https://github.com/python/cpython/settings/branches</a><p>Also, add a <code class="docutils literal notranslate"><span class="pre">needs</span> <span class="pre">backport</span> <span class="pre">to</span> <span class="pre">3.X</span></code> label to the GitHub repo.
<a class="reference external" href="https://github.com/python/cpython/labels">https://github.com/python/cpython/labels</a></p>
</li>
<li>You can now re-enable enforcement of branch settings against administrators
on GitHub. Go back to the <code class="docutils literal notranslate"><span class="pre">Settings</span> <span class="pre">|</span> <span class="pre">Branch</span></code> page:<p><a class="reference external" href="https://github.com/python/cpython/settings/branches">https://github.com/python/cpython/settings/branches</a></p>
<p>“Edit” the settings for the branch youre releasing on.
Re-check the “Include administrators” box and press the
“Save changes” button at the bottom.</p>
</li>
</ul>
<p>Now its time to twiddle the website. Almost none of this is automated, sorry.</p>
<p>To do these steps, you must have the permission to edit the website. If you
dont have that, ask someone on <a class="reference external" href="mailto:pydotorg&#37;&#52;&#48;python&#46;org">pydotorg<span>&#64;</span>python<span>&#46;</span>org</a> for the proper
permissions.</p>
<ul>
<li>Log in to <a class="reference external" href="https://www.python.org/admin">https://www.python.org/admin</a></li>
<li>Create a new “release” for the release. Currently “Releases” are
sorted under “Downloads”.<p>The easiest thing is probably to copy fields from an existing
Python release “page”, editing as you go.</p>
<p>You can use <a class="reference external" href="https://daringfireball.net/projects/markdown/syntax">Markdown</a> or
<a class="reference external" href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">reStructured Text</a>
to describe your release. The former is less verbose, while the latter has nifty
integration for things like referencing PEPs.</p>
<p>Leave the “Release page” field on the form empty.</p>
</li>
<li>“Save” the release.</li>
<li>Populate the release with the downloadable files.<p>Your friend and mine, Georg Brandl, made a lovely tool
called <code class="docutils literal notranslate"><span class="pre">add_to_pydotorg.py</span></code>. You can find it in the
<a class="reference external" href="https://github.com/python/release-tools">python/release-tools</a> repo (next to <code class="docutils literal notranslate"><span class="pre">release.py</span></code>). You run the
tool on <code class="docutils literal notranslate"><span class="pre">downloads.nyc1.psf.io</span></code>, like this:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="nv">AUTH_INFO</span><span class="o">=</span>&lt;username&gt;:&lt;python.org-api-key&gt;<span class="w"> </span>python<span class="w"> </span>add_to_pydotorg.py<span class="w"> </span>&lt;version&gt;
</pre></div>
</div>
<p>This walks the correct download directory for <code class="docutils literal notranslate"><span class="pre">&lt;version&gt;</span></code>,
looks for files marked with <code class="docutils literal notranslate"><span class="pre">&lt;version&gt;</span></code>, and populates
the “Release Files” for the correct “release” on the web
site with these files. Note that clears the “Release Files”
for the relevant version each time its run. You may run
it from any directory you like, and you can run it as
many times as you like if the files happen to change.
Keep a copy in your home directory on dl-files and
keep it fresh.</p>
<p>If new types of files are added to the release, someone will need to
update <code class="docutils literal notranslate"><span class="pre">add_to_pydotorg.py</span></code> so it recognizes these new files.
(Its best to update <code class="docutils literal notranslate"><span class="pre">add_to_pydotorg.py</span></code> when file types
are removed, too.)</p>
<p>The script will also sign any remaining files that were not
signed with Sigstore until this point. Again, if this happens,
do use your <code class="docutils literal notranslate"><span class="pre">&#64;python.org</span></code> address for this process. More info:
<a class="reference external" href="https://www.python.org/download/sigstore/">https://www.python.org/download/sigstore/</a></p>
</li>
<li>In case the CDN already cached a version of the Downloads page
without the files present, you can invalidate the cache using:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>curl<span class="w"> </span>-X<span class="w"> </span>PURGE<span class="w"> </span>https://www.python.org/downloads/release/python-XXX/
</pre></div>
</div>
</li>
<li>If this is a <strong>final</strong> release:<ul>
<li>Add the new version to the <em>Python Documentation by Version</em>
page <code class="docutils literal notranslate"><span class="pre">https://www.python.org/doc/versions/</span></code> and
remove the current version from any in development section.</li>
<li>For 3.X.Y, edit all the previous X.Y releases page(s) to
point to the new release. This includes the content field of the
<code class="docutils literal notranslate"><span class="pre">Downloads</span> <span class="pre">-&gt;</span> <span class="pre">Releases</span></code> entry for the release:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>Note:<span class="w"> </span>Python<span class="w"> </span><span class="m">3</span>.x.<span class="o">(</span>y-1<span class="o">)</span><span class="w"> </span>has<span class="w"> </span>been<span class="w"> </span>superseded<span class="w"> </span>by
<span class="sb">`</span>Python<span class="w"> </span><span class="m">3</span>.x.y<span class="w"> </span>&lt;/downloads/release/python-3xy/&gt;<span class="sb">`</span>_.
</pre></div>
</div>
<p>And, for those releases having separate release page entries
(phasing these out?), update those pages as well,
e.g. <code class="docutils literal notranslate"><span class="pre">download/releases/3.x.y</span></code>:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>Note:<span class="w"> </span>Python<span class="w"> </span><span class="m">3</span>.x.<span class="o">(</span>y-1<span class="o">)</span><span class="w"> </span>has<span class="w"> </span>been<span class="w"> </span>superseded<span class="w"> </span>by
<span class="sb">`</span>Python<span class="w"> </span><span class="m">3</span>.x.y<span class="w"> </span>&lt;/download/releases/3.x.y/&gt;<span class="sb">`</span>_.
</pre></div>
</div>
</li>
<li>Update the “Current Pre-release Testing Versions web page”.<p>Theres a page that lists all the currently-in-testing versions
of Python:</p>
<ul class="simple">
<li><a class="reference external" href="https://www.python.org/download/pre-releases/">https://www.python.org/download/pre-releases/</a></li>
</ul>
<p>Every time you make a release, one way or another youll
have to update this page:</p>
<ul class="simple">
<li>If youre releasing a version before <em>3.x.0</em>,
you should add it to this page, removing the previous pre-release
of version <em>3.x</em> as needed.</li>
<li>If youre releasing <em>3.x.0 final</em>, you need to remove the pre-release
version from this page.</li>
</ul>
<p>This is in the “Pages” category on the Django-based website, and finding
it through that UI is kind of a chore. However! If youre already logged
in to the admin interface (which, at this point, you should be), Django
will helpfully add a convenient “Edit this page” link to the top of the
page itself. So you can simply follow the link above, click on the
“Edit this page” link, and make your changes as needed. How convenient!</p>
</li>
<li>If appropriate, update the “Python Documentation by Version” page:<ul class="simple">
<li><a class="reference external" href="https://www.python.org/doc/versions/">https://www.python.org/doc/versions/</a></li>
</ul>
<p>This lists all releases of Python by version number and links to their
static (not built daily) online documentation. Theres a list at the
bottom of in-development versions, which is where all alphas/betas/RCs
should go. And yes you should be able to click on the link above then
press the shiny, exciting “Edit this page” button.</p>
</li>
</ul>
</li>
<li>Write the announcement on <a class="reference external" href="https://discuss.python.org">discuss.python.org</a>. This is the
fuzzy bit because not much can be automated. You can use an earlier
announcement as a template, but edit it for content!</li>
<li>Once the announcement is up on Discourse, send an equivalent to the
following mailing lists:<ul class="simple">
<li><a class="reference external" href="mailto:python-list&#37;&#52;&#48;python&#46;org">python-list<span>&#64;</span>python<span>&#46;</span>org</a></li>
<li><a class="reference external" href="mailto:python-announce&#37;&#52;&#48;python&#46;org">python-announce<span>&#64;</span>python<span>&#46;</span>org</a></li>
<li><a class="reference external" href="mailto:python-dev&#37;&#52;&#48;python&#46;org">python-dev<span>&#64;</span>python<span>&#46;</span>org</a></li>
</ul>
</li>
<li>Also post the announcement to the
<a class="reference external" href="http://blog.python.org">Python Insider blog</a>.
To add a new entry, go to
<a class="reference external" href="https://www.blogger.com/home">your Blogger home page, here</a>.</li>
<li>Update any release PEPs (e.g. 719) with the release dates.</li>
<li>Update the labels on <a class="reference external" href="https://github.com/python/cpython/issues">https://github.com/python/cpython/issues</a>:<ul class="simple">
<li>Flip all the <a class="reference external" href="https://github.com/python/cpython/labels/deferred-blocker">deferred-blocker</a> issues back to <a class="reference external" href="https://github.com/python/cpython/labels/release-blocker">release-blocker</a>
for the next release.</li>
<li>Add version <code class="docutils literal notranslate"><span class="pre">3.X+1</span></code> as when version <code class="docutils literal notranslate"><span class="pre">3.X</span></code> enters alpha.</li>
<li>Change non-doc feature requests to version <code class="docutils literal notranslate"><span class="pre">3.X+1</span></code> when version <code class="docutils literal notranslate"><span class="pre">3.X</span></code>
enters beta.</li>
<li>Update issues from versions that your release makes
unsupported to the next supported version.</li>
<li>Review open issues, as this might find lurking showstopper bugs,
besides reminding people to fix the easy ones they forgot about.</li>
</ul>
</li>
<li>You can delete the remote release clone branch from your repo clone.</li>
<li>If this is a <strong>new branch</strong> release, you will need to ensure various
pieces of the development infrastructure are updated for the new branch.
These include:<ul class="simple">
<li>Update the <a class="reference external" href="https://github.com/python/cpython/issues">issue tracker</a> for the new branch:
add the new version to the versions list.</li>
<li>Update the <a class="reference external" href="https://github.com/python/devguide/blob/main/include/release-cycle.json">devguide</a>
to reflect the new branches and versions.</li>
<li>Create a PR to update the supported releases table on the
<a class="reference external" href="https://www.python.org/downloads/">downloads page</a> (see
<a class="reference external" href="https://github.com/python/pythondotorg/issues/1302">python/pythondotorg#1302</a>).</li>
<li>Ensure buildbots are defined for the new branch (contact Łukasz
or Zach Ware).</li>
<li>Ensure the various GitHub bots are updated, as needed, for the
new branch, in particular, make sure backporting to the new
branch works (contact the <a class="reference external" href="https://github.com/python/core-workflow/issues">core-workflow team</a>).</li>
<li>Review the most recent commit history for the <code class="docutils literal notranslate"><span class="pre">main</span></code> and new release
branches to identify and backport any merges that might have been made
to the <code class="docutils literal notranslate"><span class="pre">main</span></code> branch during the release engineering phase and that
should be in the release branch.</li>
<li>Verify that CI is working for new PRs for the <code class="docutils literal notranslate"><span class="pre">main</span></code> and new release
branches and that the release branch is properly protected (no direct
pushes, etc).</li>
<li>Verify that the <a class="reference external" href="https://docs.python.org/">on-line docs</a> are building
properly (this may take up to 24 hours for a complete build on the website).</li>
</ul>
</li>
</ul>
</section>
<section id="what-next">
<h2><a class="toc-backref" href="#what-next" role="doc-backlink">What Next?</a></h2>
<ul class="simple">
<li>Verify! Pretend youre a user: download the files from <a class="reference external" href="https://www.python.org">www.python.org</a>, and
make Python from it. This step is too easy to overlook, and on several
occasions weve had useless release files. Once a general server problem
caused mysterious corruption of all files; once the source tarball got
built incorrectly; more than once the file upload process on SF truncated
files; and so on.</li>
<li>Rejoice. Drink. Be Merry. Write a PEP like this one. Or be
like unto Guido and take A Vacation.</li>
</ul>
<p>Youve just made a Python release!</p>
</section>
<section id="moving-to-end-of-life">
<h2><a class="toc-backref" href="#moving-to-end-of-life" role="doc-backlink">Moving to End-of-life</a></h2>
<p>Under current policy, a release branch normally reaches end-of-life status
five years after its initial release. The policy is discussed in more detail
in the <a class="reference external" href="https://devguide.python.org/developer-workflow/development-cycle/index.html">Python Developers Guide</a>.
When end-of-life is reached, there are a number of tasks that need to be
performed either directly by you as release manager or by ensuring someone
else does them. Some of those tasks include:</p>
<ul>
<li>Optionally making a final release to publish any remaining unreleased
changes.</li>
<li>Freeze the state of the release branch by creating a tag of its current HEAD
and then deleting the branch from the CPython repo. The current HEAD should
be at or beyond the final security release for the branch:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>git<span class="w"> </span>fetch<span class="w"> </span>upstream
git<span class="w"> </span>tag<span class="w"> </span>--sign<span class="w"> </span>-m<span class="w"> </span><span class="s1">&#39;Final head of the former 3.3 branch&#39;</span><span class="w"> </span><span class="m">3</span>.3<span class="w"> </span>upstream/3.3
git<span class="w"> </span>push<span class="w"> </span>upstream<span class="w"> </span>refs/tags/3.3
</pre></div>
</div>
</li>
<li>If all looks good, delete the branch. This may require the assistance of
someone with repo administrator privileges:<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>git<span class="w"> </span>push<span class="w"> </span>upstream<span class="w"> </span>--delete<span class="w"> </span><span class="m">3</span>.3<span class="w"> </span><span class="c1"># or perform from GitHub Settings page</span>
</pre></div>
</div>
</li>
<li>Remove the release from the list of “Active Python Releases” on the Downloads
page. To do this, <a class="reference external" href="https://www.python.org/admin">log in to the admin page</a>
for python.org, navigate to Boxes,
and edit the <code class="docutils literal notranslate"><span class="pre">downloads-active-releases</span></code> entry. Strip out the relevant
paragraph of HTML for your release. (Youll probably have to do the <code class="docutils literal notranslate"><span class="pre">curl</span> <span class="pre">-X</span> <span class="pre">PURGE</span></code>
trick to purge the cache if you want to confirm you made the change correctly.)</li>
<li>Add a retired notice to each release page on python.org for the retired branch.
For example:<ul class="simple">
<li><a class="reference external" href="https://www.python.org/downloads/release/python-337/">https://www.python.org/downloads/release/python-337/</a></li>
<li><a class="reference external" href="https://www.python.org/downloads/release/python-336/">https://www.python.org/downloads/release/python-336/</a></li>
</ul>
</li>
<li>In the <a class="reference external" href="https://github.com/python/devguide/blob/main/include/release-cycle.json">developers guide</a>,
set the branch status to end-of-life
and update or remove references to the branch elsewhere in the devguide.</li>
<li>Retire the release from the <a class="reference external" href="https://github.com/python/cpython/issues">issue tracker</a>. Tasks include:<ul class="simple">
<li>remove version label from list of versions</li>
<li>remove the <code class="docutils literal notranslate"><span class="pre">needs</span> <span class="pre">backport</span> <span class="pre">to</span></code> label for the retired version</li>
<li>review and dispose of open issues marked for this branch</li>
</ul>
</li>
<li>Announce the branch retirement in the usual places:<ul class="simple">
<li><a class="reference external" href="https://discuss.python.org">discuss.python.org</a></li>
<li>mailing lists (python-dev, python-list, python-announcements)</li>
<li>Python Dev blog</li>
</ul>
</li>
<li>Enjoy your retirement and bask in the glow of a job well done!</li>
</ul>
</section>
<section id="windows-notes">
<h2><a class="toc-backref" href="#windows-notes" role="doc-backlink">Windows Notes</a></h2>
<p>Windows has a MSI installer, various flavors of Windows have
“special limitations”, and the Windows installer also packs
precompiled “foreign” binaries (Tcl/Tk, expat, etc).</p>
<p>The installer is tested as part of the Azure Pipeline. In the past,
those steps were performed manually. Were keeping this for posterity.</p>
<p>Concurrent with uploading the installer, the WE installs Python
from it twice: once into the default directory suggested by the
installer, and later into a directory with embedded spaces in its
name. For each installation, the WE runs the full regression suite
from a DOS box, and both with and without -0. For maintenance
release, the WE also tests whether upgrade installations succeed.</p>
<p>The WE also tries <em>every</em> shortcut created under Start -&gt; Menu -&gt; the
Python group. When trying IDLE this way, you need to verify that
Help -&gt; Python Documentation works. When trying pydoc this way
(the “Module Docs” Start menu entry), make sure the “Start
Browser” button works, and make sure you can search for a random
module (like “random” &lt;wink&gt;) and then that the “go to selected”
button works.</p>
<p>Its amazing how much can go wrong here and even more amazing
how often last-second checkins break one of these things. If
youre “the Windows geek”, keep in mind that youre likely the
only person routinely testing on Windows, and that Windows is
simply a mess.</p>
<p>Repeat the testing for each target architecture. Try both an
Admin and a plain User (not Power User) account.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0101.rst">https://github.com/python/peps/blob/main/peps/pep-0101.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0101.rst">2024-08-04 14:50:07 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#things-you-ll-need">Things Youll Need</a></li>
<li><a class="reference internal" href="#types-of-releases">Types of Releases</a></li>
<li><a class="reference internal" href="#how-to-make-a-release">How To Make A Release</a></li>
<li><a class="reference internal" href="#what-next">What Next?</a></li>
<li><a class="reference internal" href="#moving-to-end-of-life">Moving to End-of-life</a></li>
<li><a class="reference internal" href="#windows-notes">Windows Notes</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0101.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

549
pep-0102/index.html Normal file
View File

@ -0,0 +1,549 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 102 Doing Python Micro Releases | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0102/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 102 Doing Python Micro Releases | peps.python.org'>
<meta property="og:description" content="Making a Python release is an arduous process that takes a minimum of half a days work even for an experienced releaser. Until recently, most if not all of that burden was borne by Guido himself. But several recent releases have been performed by ...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0102/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Making a Python release is an arduous process that takes a minimum of half a days work even for an experienced releaser. Until recently, most if not all of that burden was borne by Guido himself. But several recent releases have been performed by ...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 102</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 102 Doing Python Micro Releases</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Anthony Baxter &lt;anthony&#32;&#97;t&#32;interlink.com.au&gt;,
Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;,
Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Replaced by another succeeding PEP">Superseded</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">09-Jan-2002</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
<dt class="field-even">Superseded-By<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../pep-0101/">101</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#replacement-note">Replacement Note</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#how-to-make-a-release">How to Make A Release</a></li>
<li><a class="reference internal" href="#what-next">What Next?</a></li>
<li><a class="reference internal" href="#final-release-notes">Final Release Notes</a></li>
<li><a class="reference internal" href="#windows-notes">Windows Notes</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="replacement-note">
<h2><a class="toc-backref" href="#replacement-note" role="doc-backlink">Replacement Note</a></h2>
<p>Although the size of the to-do list in this PEP is much less scary
than that in <a class="pep reference internal" href="../pep-0101/" title="PEP 101 Doing Python Releases 101">PEP 101</a>, it turns out not to be enough justification
for the duplication of information, and with it, the danger of one
of the copies to become out of date. Therefore, this PEP is not
maintained anymore, and micro releases are fully covered by <a class="pep reference internal" href="../pep-0101/" title="PEP 101 Doing Python Releases 101">PEP 101</a>.</p>
</section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Making a Python release is an arduous process that takes a
minimum of half a days work even for an experienced releaser.
Until recently, most if not all of that burden was borne by
Guido himself. But several recent releases have been performed by
other folks, so this PEP attempts to collect, in one place, all
the steps needed to make a Python bugfix release.</p>
<p>The major Python release process is covered in <a class="pep reference internal" href="../pep-0101/" title="PEP 101 Doing Python Releases 101">PEP 101</a> - this PEP
is just <a class="pep reference internal" href="../pep-0101/" title="PEP 101 Doing Python Releases 101">PEP 101</a>, trimmed down to only include the bits that are
relevant for micro releases, a.k.a. patch, or bug fix releases.</p>
<p>It is organized as a recipe and you can actually print this out and
check items off as you complete them.</p>
</section>
<section id="how-to-make-a-release">
<h2><a class="toc-backref" href="#how-to-make-a-release" role="doc-backlink">How to Make A Release</a></h2>
<p>Here are the steps taken to make a Python release. Some steps are
more fuzzy than others because theres little that can be
automated (e.g. writing the NEWS entries). Where a step is
usually performed by An Expert, the name of that expert is given.
Otherwise, assume the step is done by the Release Manager (RM),
the designated person performing the release. Almost every place
the RM is mentioned below, this step can also be done by the BDFL
of course!</p>
<p>XXX: We should include a dependency graph to illustrate the steps
that can be taken in parallel, or those that depend on other
steps.</p>
<p>We use the following conventions in the examples below. Where a
release number is given, it is of the form X.Y.MaA, e.g. 2.1.2c1
for Python 2.1.2 release candidate 1, where “a” == alpha, “b” ==
beta, “c” == release candidate. Final releases are tagged with
“releaseXYZ” in CVS. The micro releases are made from the
maintenance branch of the major release, e.g. Python 2.1.2 is made
from the release21-maint branch.</p>
<ol class="arabic">
<li>Send an email to <a class="reference external" href="mailto:python-dev&#37;&#52;&#48;python&#46;org">python-dev<span>&#64;</span>python<span>&#46;</span>org</a> indicating the release is
about to start.</li>
<li>Put a freeze on check ins into the maintenance branch. At this
point, nobody except the RM should make any commits to the branch
(or his duly assigned agents, i.e. Guido the BDFL, Fred Drake for
documentation, or Thomas Heller for Windows). If the RM screwed up
and some desperate last minute change to the branch is
necessary, it can mean extra work for Fred and Thomas. So try to
avoid this!</li>
<li>On the branch, change Include/patchlevel.h in two places, to
reflect the new version number youve just created. Youll want
to change the PY_VERSION macro, and one or several of the
version subpart macros just above PY_VERSION, as appropriate.</li>
<li>Change the “%define version” line of Misc/RPM/python-2.3.spec to the
same string as <code class="docutils literal notranslate"><span class="pre">PY_VERSION</span></code> was changed to above. E.g:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">%</span><span class="n">define</span> <span class="n">version</span> <span class="mf">2.3.1</span>
</pre></div>
</div>
<p>You also probably want to reset the %define release line
to 1pydotorg if its not already that.</p>
</li>
<li>If youre changing the version number for Python (e.g. from
Python 2.1.1 to Python 2.1.2), you also need to update the
README file, which has a big banner at the top proclaiming its
identity. Dont do this if youre just releasing a new alpha or
beta release, but /do/ do this if youre release a new micro,
minor or major release.</li>
<li>The LICENSE file also needs to be changed, due to several
references to the release number. As for the README file, changing
these are necessary for a new micro, minor or major release.<p>The LICENSE file contains a table that describes the legal
heritage of Python; you should add an entry for the X.Y.Z
release you are now making. You should update this table in the
LICENSE file on the CVS trunk too.</p>
</li>
<li>When the year changes, copyright legends need to be updated in
many places, including the README and LICENSE files.</li>
<li>For the Windows build, additional files have to be updated.<p>PCbuild/BUILDno.txt contains the Windows build number, see the
instructions in this file how to change it. Saving the project
file PCbuild/pythoncore.dsp results in a change to
PCbuild/pythoncore.dsp as well.</p>
<p>PCbuild/python20.wse sets up the Windows installer version
resource (displayed when you right-click on the installer .exe
and select Properties), and also contains the Python version
number.</p>
<p>(Before version 2.3.2, it was required to manually edit
PC/python_nt.rc, this step is now automated by the build
process.)</p>
</li>
<li>After starting the process, the most important thing to do next
is to update the Misc/NEWS file. Thomas will need this in order to
do the Windows release and he likes to stay up late. This step
can be pretty tedious, so its best to get to it immediately
after making the branch, or even before youve made the branch.
The sooner the better (but again, watch for new checkins up
until the release is made!)<p>Add high level items new to this release. E.g. if were
releasing 2.2a3, there must be a section at the top of the file
explaining “Whats new in Python 2.2a3”. It will be followed by
a section entitled “Whats new in Python 2.2a2”.</p>
<p>Note that you /hope/ that as developers add new features to the
trunk, theyve updated the NEWS file accordingly. You cant be
positive, so double check. If youre a Unix weenie, it helps to
verify with Thomas about changes on Windows, and Jack Jansen
about changes on the Mac.</p>
<p>This command should help you (but substitute the correct -r tag!):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">%</span> <span class="n">cvs</span> <span class="n">log</span> <span class="o">-</span><span class="n">rr22a1</span><span class="p">:</span> <span class="o">|</span> <span class="n">python</span> <span class="n">Tools</span><span class="o">/</span><span class="n">scripts</span><span class="o">/</span><span class="n">logmerge</span><span class="o">.</span><span class="n">py</span> <span class="o">&gt;</span> <span class="o">/</span><span class="n">tmp</span><span class="o">/</span><span class="n">news</span><span class="o">.</span><span class="n">txt</span>
</pre></div>
</div>
<p>IOW, youre printing out all the cvs log entries from the
previous release until now. You can then troll through the
news.txt file looking for interesting things to add to NEWS.</p>
</li>
<li>Check your NEWS changes into the maintenance branch. Its easy
to forget to update the release date in this file!</li>
<li>Check in any changes to IDLEs NEWS.txt. Update the header in
Lib/idlelib/NEWS.txt to reflect its release version and date.
Update the IDLE version in Lib/idlelib/idlever.py to match.</li>
</ol>
<ol class="arabic" start="11">
<li>Once the release process has started, the documentation needs to
be built and posted on python.org according to the instructions
in <a class="pep reference internal" href="../pep-0101/" title="PEP 101 Doing Python Releases 101">PEP 101</a>.<p>Note that Fred is responsible both for merging doc changes from
the trunk to the branch AND for merging any branch changes from
the branch to the trunk during the cleaning up phase.
Basically, if its in Doc/ Fred will take care of it.</p>
</li>
<li>Thomas compiles everything with MSVC 6.0 SP5, and moves the
python23.chm file into the src/chm directory. The installer
executable is then generated with Wise Installation System.<p>The installer includes the MSVC 6.0 runtime in the files
MSVCRT.DLL and MSVCIRT.DLL. It leads to disaster if these files
are taken from the system directory of the machine where the
installer is built, instead it must be absolutely made sure that
these files come from the VCREDIST.EXE redistributable package
contained in the MSVC SP5 CD. VCREDIST.EXE must be unpacked
with winzip, and the Wise Installation System prompts for the
directory.</p>
<p>After building the installer, it should be opened with winzip,
and the MS dlls extracted again and check for the same version
number as those unpacked from VCREDIST.EXE.</p>
<p>Thomas uploads this file to the starship. He then sends the RM
a notice which includes the location and MD5 checksum of the
Windows executable.</p>
<p>Note that Thomass creation of the Windows executable may generate
a few more commits on the branch. Thomas will be responsible for
merging Windows-specific changes from trunk to branch, and from
branch to trunk.</p>
</li>
<li>Sean performs his Red Hat magic, generating a set of RPMs. He
uploads these files to python.org. He then sends the RM a notice
which includes the location and MD5 checksum of the RPMs.</li>
<li>Its Build Time!<p>Now, youre ready to build the source tarball. First cd to your
working directory for the branch. E.g.
% cd …/python-22a3</p>
</li>
<li>Do a “cvs update” in this directory. Do NOT include the -A flag!<p>You should not see any “M” files, but you may see several “P”
and/or “U” files. I.e. you better not have any uncommitted
changes in your working directory, but you may pick up some of
Freds or Thomass last minute changes.</p>
</li>
<li>Now tag the branch using a symbolic name like “rXYMaZ”,
e.g. r212<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">%</span> <span class="n">cvs</span> <span class="n">tag</span> <span class="n">r212</span>
</pre></div>
</div>
<p>Be sure to tag only the python/dist/src subdirectory of the
Python CVS tree!</p>
</li>
<li>Change to a neutral directory, i.e. one in which you can do a
fresh, virgin, cvs export of the branch. You will be creating a
new directory at this location, to be named “Python-X.Y.M”. Do
a CVS export of the tagged branch.<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">%</span> <span class="n">cd</span> <span class="o">~</span>
<span class="o">%</span> <span class="n">cvs</span> <span class="o">-</span><span class="n">d</span> <span class="n">cvs</span><span class="o">.</span><span class="n">sf</span><span class="o">.</span><span class="n">net</span><span class="p">:</span><span class="o">/</span><span class="n">cvsroot</span><span class="o">/</span><span class="n">python</span> <span class="n">export</span> <span class="o">-</span><span class="n">rr212</span> \
<span class="o">-</span><span class="n">d</span> <span class="n">Python</span><span class="o">-</span><span class="mf">2.1.2</span> <span class="n">python</span><span class="o">/</span><span class="n">dist</span><span class="o">/</span><span class="n">src</span>
</pre></div>
</div>
</li>
<li>Generate the tarball. Note that were not using the z option
on the tar command because 1) thats only supported by GNU tar
as far as we know, and 2) were going to max out the compression
level, which isnt a supported option. We generate both tar.gz
tar.bz2 formats, as the latter is about 1/6th smaller.<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">%</span> <span class="n">tar</span> <span class="o">-</span><span class="n">cf</span> <span class="o">-</span> <span class="n">Python</span><span class="o">-</span><span class="mf">2.1.2</span> <span class="o">|</span> <span class="n">gzip</span> <span class="o">-</span><span class="mi">9</span> <span class="o">&gt;</span> <span class="n">Python</span><span class="o">-</span><span class="mf">2.1.2</span><span class="o">.</span><span class="n">tgz</span>
<span class="o">%</span> <span class="n">tar</span> <span class="o">-</span><span class="n">cf</span> <span class="o">-</span> <span class="n">Python</span><span class="o">-</span><span class="mf">2.1.2</span> <span class="o">|</span> <span class="n">bzip2</span> <span class="o">-</span><span class="mi">9</span> <span class="o">&gt;</span> <span class="n">Python</span><span class="o">-</span><span class="mf">2.1.2</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">bz2</span>
</pre></div>
</div>
</li>
<li>Calculate the MD5 checksum of the tgz and tar.bz2 files you
just created<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">%</span> <span class="n">md5sum</span> <span class="n">Python</span><span class="o">-</span><span class="mf">2.1.2</span><span class="o">.</span><span class="n">tgz</span>
</pre></div>
</div>
<p>Note that if you dont have the md5sum program, there is a
Python replacement in the Tools/scripts/md5sum.py file.</p>
</li>
<li>Create GPG keys for each of the files.<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">%</span> <span class="n">gpg</span> <span class="o">-</span><span class="n">ba</span> <span class="n">Python</span><span class="o">-</span><span class="mf">2.1.2</span><span class="o">.</span><span class="n">tgz</span>
<span class="o">%</span> <span class="n">gpg</span> <span class="o">-</span><span class="n">ba</span> <span class="n">Python</span><span class="o">-</span><span class="mf">2.1.2</span><span class="o">.</span><span class="n">tar</span><span class="o">.</span><span class="n">bz2</span>
<span class="o">%</span> <span class="n">gpg</span> <span class="o">-</span><span class="n">ba</span> <span class="n">Python</span><span class="o">-</span><span class="mf">2.1.2</span><span class="o">.</span><span class="n">exe</span>
</pre></div>
</div>
</li>
<li>Now you want to perform the very important step of checking the
tarball you just created, to make sure a completely clean,
virgin build passes the regression test. Here are the best
steps to take:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>% cd /tmp
% tar zxvf ~/Python-2.1.2.tgz
% cd Python-2.1.2
% ls
(Do things look reasonable?)
% ./configure
(Loads of configure output)
% make test
(Do all the expected tests pass?)
</pre></div>
</div>
<p>If the tests pass, then you can feel good that the tarball is
fine. If some of the tests fail, or anything else about the
freshly unpacked directory looks weird, you better stop now and
figure out what the problem is.</p>
</li>
<li>You need to upload the tgz and the exe file to creosote.python.org.
This step can take a long time depending on your network
bandwidth. scp both files from your own machine to creosote.</li>
<li>While youre waiting, you can start twiddling the web pages to
include the announcement.<ol class="arabic">
<li>In the top of the python.org web site CVS tree, create a
subdirectory for the X.Y.Z release. You can actually copy an
earlier patch releases subdirectory, but be sure to delete
the X.Y.Z/CVS directory and “cvs add X.Y.Z”, for example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">%</span> <span class="n">cd</span> <span class="o">.../</span><span class="n">pydotorg</span>
<span class="o">%</span> <span class="n">cp</span> <span class="o">-</span><span class="n">r</span> <span class="mf">2.2.2</span> <span class="mf">2.2.3</span>
<span class="o">%</span> <span class="n">rm</span> <span class="o">-</span><span class="n">rf</span> <span class="mf">2.2.3</span><span class="o">/</span><span class="n">CVS</span>
<span class="o">%</span> <span class="n">cvs</span> <span class="n">add</span> <span class="mf">2.2.3</span>
<span class="o">%</span> <span class="n">cd</span> <span class="mf">2.2.3</span>
</pre></div>
</div>
</li>
<li>Edit the files for content: usually you can globally replace
X.Ya(Z-1) with X.YaZ. However, youll need to think about the
“Whats New?” section.</li>
<li>Copy the Misc/NEWS file to NEWS.txt in the X.Y.Z directory for
python.org; this contains the “full scoop” of changes to
Python since the previous release for this version of Python.</li>
<li>Copy the .asc GPG signatures you created earlier here as well.</li>
<li>Also, update the MD5 checksums.</li>
<li>Preview the web page by doing a “make” or “make install” (as
long as youve created a new directory for this release!)</li>
<li>Similarly, edit the ../index.ht file, i.e. the python.org home
page. In the Big Blue Announcement Block, move the paragraph
for the new version up to the top and boldify the phrase
“Python X.YaZ is out”. Edit for content, and preview locally,
but do NOT do a “make install” yet!</li>
</ol>
</li>
<li>Now were waiting for the scp to creosote to finish. Da de da,
da de dum, hmm, hmm, dum de dum.</li>
<li>Once thats done you need to go to creosote.python.org and move
all the files in place over there. Our policy is that every
Python version gets its own directory, but each directory may
contain several releases. We keep all old releases, moving them
into a “prev” subdirectory when we have a new release.<p>So, theres a directory called “2.2” which contains
Python-2.2a2.exe and Python-2.2a2.tgz, along with a “prev”
subdirectory containing Python-2.2a1.exe and Python-2.2a1.tgz.</p>
<p>So…</p>
<ol class="arabic simple">
<li>On creosote, cd to ~ftp/pub/python/X.Y creating it if
necessary.</li>
<li>Move the previous release files to a directory called “prev”
creating the directory if necessary (make sure the directory
has g+ws bits on). If this is the first alpha release of a
new Python version, skip this step.</li>
<li>Move the .tgz file and the .exe file to this directory. Make
sure they are world readable. They should also be group
writable, and group-owned by webmaster.</li>
<li>md5sum the files and make sure they got uploaded intact.</li>
</ol>
</li>
<li>the X.Y/bugs.ht file if necessary. It is best to get
BDFL input for this step.</li>
<li>Go up to the parent directory (i.e. the root of the web page
hierarchy) and do a “make install” there. Youre release is now
live!</li>
<li>Now its time to write the announcement for the mailing lists.
This is the fuzzy bit because not much can be automated. You
can use one of Guidos earlier announcements as a template, but
please edit it for content!<p>Once the announcement is ready, send it to the following
addresses:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span><span class="o">-</span><span class="nb">list</span><span class="nd">@python</span><span class="o">.</span><span class="n">org</span>
<span class="n">python</span><span class="o">-</span><span class="n">announce</span><span class="nd">@python</span><span class="o">.</span><span class="n">org</span>
<span class="n">python</span><span class="o">-</span><span class="n">dev</span><span class="nd">@python</span><span class="o">.</span><span class="n">org</span>
</pre></div>
</div>
</li>
<li>Send a SourceForge News Item about the release. From the
projects “menu bar”, select the “News” link; once in News,
select the “Submit” link. Type a suitable subject (e.g. “Python
2.2c1 released” :-) in the Subject box, add some text to the
Details box (at the very least including the release URL at
www.python.org and the fact that youre happy with the release)
and click the SUBMIT button.<p>Feel free to remove any old news items.</p>
</li>
</ol>
<p>Now its time to do some cleanup. These steps are very important!</p>
<ol class="arabic">
<li>Edit the file Include/patchlevel.h so that the PY_VERSION
string says something like “X.YaZ+”. Note the trailing +
indicating that the trunk is going to be moving forward with
development. E.g. the line should look like:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">#define PY_VERSION &quot;2.1.2+&quot;</span>
</pre></div>
</div>
<p>Make sure that the other <code class="docutils literal notranslate"><span class="pre">PY_</span></code> version macros contain the
correct values. Commit this change.</p>
</li>
<li>For the extra paranoid, do a completely clean test of the
release. This includes downloading the tarball from
www.python.org.</li>
<li>Make sure the md5 checksums match. Then unpack the tarball,
and do a clean make test.<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">%</span> <span class="n">make</span> <span class="n">distclean</span>
<span class="o">%</span> <span class="o">./</span><span class="n">configure</span>
<span class="o">%</span> <span class="n">make</span> <span class="n">test</span>
</pre></div>
</div>
<p>To ensure that the regression test suite passes. If not, you
screwed up somewhere!</p>
</li>
</ol>
<p>Step 5 …</p>
<p>Verify! This can be interleaved with Step 4. Pretend youre a
user: download the files from python.org, and make Python from
it. This step is too easy to overlook, and on several occasions
weve had useless release files. Once a general server problem
caused mysterious corruption of all files; once the source tarball
got built incorrectly; more than once the file upload process on
SF truncated files; and so on.</p>
</section>
<section id="what-next">
<h2><a class="toc-backref" href="#what-next" role="doc-backlink">What Next?</a></h2>
<p>Rejoice. Drink. Be Merry. Write a PEP like this one. Or be
like unto Guido and take A Vacation.</p>
<p>Youve just made a Python release!</p>
<p>Actually, there is one more step. You should turn over ownership
of the branch to Jack Jansen. All this means is that now he will
be responsible for making commits to the branch. Hes going to
use this to build the MacOS versions. He may send you information
about the Mac release that should be merged into the informational
pages on www.python.org. When hes done, hell tag the branch
something like “rX.YaZ-mac”. Hell also be responsible for
merging any Mac-related changes back into the trunk.</p>
</section>
<section id="final-release-notes">
<h2><a class="toc-backref" href="#final-release-notes" role="doc-backlink">Final Release Notes</a></h2>
<p>The Final release of any major release, e.g. Python 2.2 final, has
special requirements, specifically because it will be one of the
longest lived releases (i.e. betas dont last more than a couple
of weeks, but final releases can last for years!).</p>
<p>For this reason we want to have a higher coordination between the
three major releases: Windows, Mac, and source. The Windows and
source releases benefit from the close proximity of the respective
release-bots. But the Mac-bot, Jack Jansen, is 6 hours away. So
we add this extra step to the release process for a final
release:</p>
<ol class="arabic simple">
<li>Hold up the final release until Jack approves, or until we
lose patience &lt;wink&gt;.</li>
</ol>
<p>The python.org site also needs some tweaking when a new bugfix release
is issued.</p>
<ol class="arabic simple" start="2">
<li>The documentation should be installed at doc/&lt;version&gt;/.</li>
<li>Add a link from doc/&lt;previous-minor-release&gt;/index.ht to the
documentation for the new version.</li>
<li>All older doc/&lt;old-release&gt;/index.ht files should be updated to
point to the documentation for the new version.</li>
<li>/robots.txt should be modified to prevent the old versions
documentation from being crawled by search engines.</li>
</ol>
</section>
<section id="windows-notes">
<h2><a class="toc-backref" href="#windows-notes" role="doc-backlink">Windows Notes</a></h2>
<p>Windows has a GUI installer, various flavors of Windows have
“special limitations”, and the Windows installer also packs
precompiled “foreign” binaries (Tcl/Tk, expat, etc). So Windows
testing is tiresome but very necessary.</p>
<p>Concurrent with uploading the installer, Thomas installs Python
from it twice: once into the default directory suggested by the
installer, and later into a directory with embedded spaces in its
name. For each installation, he runs the full regression suite
from a DOS box, and both with and without -0.</p>
<p>He also tries <strong>every</strong> shortcut created under Start -&gt; Menu -&gt; the
Python group. When trying IDLE this way, you need to verify that
Help -&gt; Python Documentation works. When trying pydoc this way
(the “Module Docs” Start menu entry), make sure the “Start
Browser” button works, and make sure you can search for a random
module (Thomas uses “random” &lt;wink&gt;) and then that the “go to
selected” button works.</p>
<p>Its amazing how much can go wrong here and even more amazing
how often last-second checkins break one of these things. If
youre “the Windows geek”, keep in mind that youre likely the
only person routinely testing on Windows, and that Windows is
simply a mess.</p>
<p>Repeat all of the above on at least one flavor of Win9x, and one
of NT/2000/XP. On NT/2000/XP, try both an Admin and a plain User
(not Power User) account.</p>
<p>WRT Step 5 above (verify the release media), since by the time
release files are ready to download Thomas has generally run many
Windows tests on the installer he uploaded, he usually doesnt do
anything for Step 5 except a full byte-comparison (“fc /b” if
using a Windows shell) of the downloaded file against the file he
uploaded.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0102.rst">https://github.com/python/peps/blob/main/peps/pep-0102.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0102.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#replacement-note">Replacement Note</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#how-to-make-a-release">How to Make A Release</a></li>
<li><a class="reference internal" href="#what-next">What Next?</a></li>
<li><a class="reference internal" href="#final-release-notes">Final Release Notes</a></li>
<li><a class="reference internal" href="#windows-notes">Windows Notes</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0102.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

1107
pep-0103/index.html Normal file

File diff suppressed because it is too large Load Diff

186
pep-0160/index.html Normal file
View File

@ -0,0 +1,186 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 160 Python 1.6 Release Schedule | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0160/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 160 Python 1.6 Release Schedule | peps.python.org'>
<meta property="og:description" content="This PEP describes the Python 1.6 release schedule. The CVS revision history of this file contains the definitive historical record.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0160/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the Python 1.6 release schedule. The CVS revision history of this file contains the definitive historical record.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 160</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 160 Python 1.6 Release Schedule</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Fred L. Drake, Jr. &lt;fred&#32;&#97;t&#32;fdrake.net&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Topic<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../topic/release/">Release</a></dd>
<dt class="field-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">25-Jul-2000</dd>
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
<dd class="field-even">1.6</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#schedule">Schedule</a></li>
<li><a class="reference internal" href="#features">Features</a></li>
<li><a class="reference internal" href="#mechanism">Mechanism</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes the Python 1.6 release schedule. The CVS
revision history of this file contains the definitive historical
record.</p>
<p>This release will be produced by BeOpen PythonLabs staff for the
Corporation for National Research Initiatives (CNRI).</p>
</section>
<section id="schedule">
<h2><a class="toc-backref" href="#schedule" role="doc-backlink">Schedule</a></h2>
<ul class="simple">
<li>August 1: 1.6 beta 1 release (planned).</li>
<li>August 3: 1.6 beta 1 release (actual).</li>
<li>August 15: 1.6 final release (planned).</li>
<li>September 5: 1.6 final release (actual).</li>
</ul>
</section>
<section id="features">
<h2><a class="toc-backref" href="#features" role="doc-backlink">Features</a></h2>
<p>A number of features are required for Python 1.6 in order to
fulfill the various promises that have been made. The following
are required to be fully operational, documented, and forward
compatible with the plans for Python 2.0:</p>
<ul class="simple">
<li>Unicode support: The Unicode object defined for Python 2.0 must be provided,
including all methods and codec support.</li>
<li>SRE: Fredrik Lundhs new regular expression engine will be used
to provide support for both 8-bit strings and Unicode strings. It must pass
the regression test used for the pcre-based version of the re module.</li>
<li>The curses module was in the middle of a transformation to a package, so the
final form was adopted.</li>
</ul>
</section>
<section id="mechanism">
<h2><a class="toc-backref" href="#mechanism" role="doc-backlink">Mechanism</a></h2>
<p>The release will be created as a branch from the development tree
rooted at CNRIs close of business on 16 May 2000. Patches
required from more recent checkins will be merged in by moving the
branch tag on individual files whenever possible in order to
reduce mailing list clutter and avoid divergent and incompatible
implementations.</p>
<p>The branch tag is “cnri-16-start”.</p>
<p>Patches and features will be merged to the extent required to pass
regression tests in effect on 16 May 2000.</p>
<p>The beta release is tagged “r16b1” in the CVS repository, and the
final Python 1.6 release is tagged “release16” in the repository.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0160.rst">https://github.com/python/peps/blob/main/peps/pep-0160.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0160.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#schedule">Schedule</a></li>
<li><a class="reference internal" href="#features">Features</a></li>
<li><a class="reference internal" href="#mechanism">Mechanism</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0160.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

478
pep-0200/index.html Normal file
View File

@ -0,0 +1,478 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 200 Python 2.0 Release Schedule | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0200/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 200 Python 2.0 Release Schedule | peps.python.org'>
<meta property="og:description" content="This PEP describes the Python 2.0 release schedule, tracking the status and ownership of the major new features, summarizes discussions held in mailing list forums, and provides URLs for further information, patches, and other outstanding issues. The C...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0200/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the Python 2.0 release schedule, tracking the status and ownership of the major new features, summarizes discussions held in mailing list forums, and provides URLs for further information, patches, and other outstanding issues. The C...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 200</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 200 Python 2.0 Release Schedule</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Jeremy Hylton &lt;jeremy&#32;&#97;t&#32;alum.mit.edu&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Topic<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../topic/release/">Release</a></dd>
<dt class="field-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">12-Jul-2000</dd>
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
<dd class="field-even">2.0</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#release-schedule">Release Schedule</a></li>
<li><a class="reference internal" href="#previous-milestones">Previous milestones</a></li>
<li><a class="reference internal" href="#what-is-release-candidate-1">What is release candidate 1?</a></li>
<li><a class="reference internal" href="#guidelines-for-submitting-patches-and-making-changes">Guidelines for submitting patches and making changes</a></li>
<li><a class="reference internal" href="#failing-test-cases-need-to-get-fixed">Failing test cases need to get fixed</a></li>
<li><a class="reference internal" href="#open-items-need-to-be-resolved-before-2-0-final-release">Open items Need to be resolved before 2.0 final release</a></li>
<li><a class="reference internal" href="#accepted-and-in-progress">Accepted and in progress</a></li>
<li><a class="reference internal" href="#open-proposed-but-not-accepted-or-rejected">Open: proposed but not accepted or rejected</a></li>
<li><a class="reference internal" href="#previously-failing-test-cases">Previously failing test cases</a></li>
<li><a class="reference internal" href="#open-items-completed-fixed">Open items completed/fixed</a></li>
<li><a class="reference internal" href="#accepted-and-completed">Accepted and completed</a></li>
<li><a class="reference internal" href="#postponed">Postponed</a></li>
<li><a class="reference internal" href="#rejected">Rejected</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes the Python 2.0 release schedule, tracking the
status and ownership of the major new features, summarizes discussions
held in mailing list forums, and provides URLs for further
information, patches, and other outstanding issues. The CVS revision
history of this file contains the definitive historical record.</p>
</section>
<section id="release-schedule">
<h2><a class="toc-backref" href="#release-schedule" role="doc-backlink">Release Schedule</a></h2>
<p>[revised 5 Oct 2000]</p>
<ul class="simple">
<li>26-Sep-2000: 2.0 beta 2</li>
<li>9-Oct-2000: 2.0 release candidate 1 (2.0c1)</li>
<li>16-Oct-2000: 2.0 final</li>
</ul>
</section>
<section id="previous-milestones">
<h2><a class="toc-backref" href="#previous-milestones" role="doc-backlink">Previous milestones</a></h2>
<ul class="simple">
<li>14-Aug-2000: All 2.0 PEPs finished / feature freeze</li>
<li>5-Sep-2000: 2.0 beta 1</li>
</ul>
</section>
<section id="what-is-release-candidate-1">
<h2><a class="toc-backref" href="#what-is-release-candidate-1" role="doc-backlink">What is release candidate 1?</a></h2>
<p>We believe that release candidate 1 will fix all known bugs that we
intend to fix for the 2.0 final release. This release should be a bit
more stable than the previous betas. We would like to see even more
widespread testing before the final release, so we are producing this
release candidate. The final release will be exactly the same unless
any show-stopping (or brown bag) bugs are found by testers of the
release candidate.</p>
</section>
<section id="guidelines-for-submitting-patches-and-making-changes">
<h2><a class="toc-backref" href="#guidelines-for-submitting-patches-and-making-changes" role="doc-backlink">Guidelines for submitting patches and making changes</a></h2>
<p>Use good sense when committing changes. You should know what we mean
by good sense or we wouldnt have given you commit privileges &lt;0.5
wink&gt;. Some specific examples of good sense include:</p>
<ul class="simple">
<li>Do whatever the dictator tells you.</li>
<li>Discuss any controversial changes on python-dev first. If you get
a lot of +1 votes and no -1 votes, make the change. If you get a
some -1 votes, think twice; consider asking Guido what he thinks.</li>
<li>If the change is to code you contributed, it probably makes sense
for you to fix it.</li>
<li>If the change affects code someone else wrote, it probably makes
sense to ask him or her first.</li>
<li>You can use the SF Patch Manager to submit a patch and assign it to
someone for review.</li>
</ul>
<p>Any significant new feature must be described in a PEP and approved
before it is checked in.</p>
<p>Any significant code addition, such as a new module or large patch,
must include test cases for the regression test and documentation. A
patch should not be checked in until the tests and documentation are
ready.</p>
<p>If you fix a bug, you should write a test case that would have caught
the bug.</p>
<p>If you commit a patch from the SF Patch Manager or fix a bug from the
Jitterbug database, be sure to reference the patch/bug number in the
CVS log message. Also be sure to change the status in the patch
manager or bug database (if you have access to the bug database).</p>
<p>It is not acceptable for any checked in code to cause the regression
test to fail. If a checkin causes a failure, it must be fixed within
24 hours or it will be backed out.</p>
<p>All contributed C code must be ANSI C. If possible check it with two
different compilers, e.g. gcc and MSVC.</p>
<p>All contributed Python code must follow Guidos Python style guide.
<a class="reference external" href="http://www.python.org/doc/essays/styleguide.html">http://www.python.org/doc/essays/styleguide.html</a></p>
<p>It is understood that any code contributed will be released under an
Open Source license. Do not contribute code if it cant be released
this way.</p>
</section>
<section id="failing-test-cases-need-to-get-fixed">
<h2><a class="toc-backref" href="#failing-test-cases-need-to-get-fixed" role="doc-backlink">Failing test cases need to get fixed</a></h2>
<p>We need to resolve errors in the regression test suite quickly.
Changes should not be committed to the CVS tree unless the regression
test runs cleanly with the changes applied. If it fails, there may be
bugs lurking in the code. (There may be bugs anyway, but thats
another matter.) If the test cases are known to fail, they serve no
useful purpose.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">test</span> <span class="n">case</span> <span class="n">platform</span> <span class="n">date</span> <span class="n">reported</span>
<span class="o">---------</span> <span class="o">--------</span> <span class="o">-------------</span>
<span class="n">test_mmap</span> <span class="n">Win</span> <span class="n">ME</span> <span class="mi">03</span><span class="o">-</span><span class="n">Sep</span><span class="o">-</span><span class="mi">2000</span> <span class="n">Windows</span> <span class="mi">2</span><span class="n">b1p2</span> <span class="n">prelease</span>
<span class="p">[</span><span class="mi">04</span><span class="o">-</span><span class="n">Sep</span><span class="o">-</span><span class="mi">2000</span> <span class="n">tim</span>
<span class="n">reported</span> <span class="n">by</span> <span class="n">Audun</span> <span class="n">S</span><span class="o">.</span> <span class="n">Runde</span> <span class="n">mailto</span><span class="p">:</span><span class="n">audun</span><span class="nd">@mindspring</span><span class="o">.</span><span class="n">com</span>
<span class="n">the</span> <span class="n">mmap</span> <span class="n">constructor</span> <span class="n">fails</span> <span class="n">w</span><span class="o">/</span>
<span class="ne">WindowsError</span><span class="p">:</span> <span class="p">[</span><span class="n">Errno</span> <span class="mi">6</span><span class="p">]</span> <span class="n">The</span> <span class="n">handle</span> <span class="ow">is</span> <span class="n">invalid</span>
<span class="n">since</span> <span class="n">there</span> <span class="n">are</span> <span class="n">no</span> <span class="n">reports</span> <span class="n">of</span> <span class="n">this</span> <span class="n">failing</span> <span class="n">on</span> <span class="n">other</span>
<span class="n">flavors</span> <span class="n">of</span> <span class="n">Windows</span><span class="p">,</span> <span class="n">this</span> <span class="n">looks</span> <span class="n">like</span> <span class="n">to</span> <span class="n">be</span> <span class="n">an</span> <span class="n">ME</span> <span class="n">bug</span>
<span class="p">]</span>
</pre></div>
</div>
</section>
<section id="open-items-need-to-be-resolved-before-2-0-final-release">
<h2><a class="toc-backref" href="#open-items-need-to-be-resolved-before-2-0-final-release" role="doc-backlink">Open items Need to be resolved before 2.0 final release</a></h2>
<p>Decide whether cycle-gc should be enabled by default.</p>
<p>Resolve compatibility issues between core xml package and the XML-SIG
XML package.</p>
<p>Update Tools/compiler so that it is compatible with list
comprehensions, import as, and any other new language features.</p>
<p>Improve code coverage of test suite.</p>
<p>Finish writing the PEPs for the features that went out with 2.0b1(!
sad, but realistic well get better with practice).</p>
<p>Major effort to whittle the bug database down to size. Ive (tim)
seen this before: if you can keep all the open bugs fitting on one
screen, people will generally keep it that way. But let it slobber
over a screen for a month, &amp; it just goes to hell (no “visible
progress” indeed!).</p>
</section>
<section id="accepted-and-in-progress">
<h2><a class="toc-backref" href="#accepted-and-in-progress" role="doc-backlink">Accepted and in progress</a></h2>
<ul class="simple">
<li>Currently none left. [4-Sep-2000 guido]</li>
</ul>
</section>
<section id="open-proposed-but-not-accepted-or-rejected">
<h2><a class="toc-backref" href="#open-proposed-but-not-accepted-or-rejected" role="doc-backlink">Open: proposed but not accepted or rejected</a></h2>
<ul class="simple">
<li>There are a number of open patches again. We need to clear these
out soon.</li>
</ul>
</section>
<section id="previously-failing-test-cases">
<h2><a class="toc-backref" href="#previously-failing-test-cases" role="doc-backlink">Previously failing test cases</a></h2>
<p>If you find a test bouncing between this section and the previous one,
the code its testing is in trouble!</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>test case platform date reported
--------- -------- -------------
test_fork1 Linux 26-Jul-2000
[28-aug-2000 fixed by cgw; solution is to create copies of
lock in child process]
[19-Aug-2000 tim
Charles Waldman whipped up a patch to give child processes a new
&quot;global lock&quot;:
http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=101226&amp;group_id=5470
While this doesn&#39;t appear to address the symptoms we *saw*, it
*does* so far appear to be fixing the failing cases anyway
]
test_parser all 22-Aug-2000
test_posixpath all 22-Aug-2000
test_popen2 Win32 26-Jul-2000
[31-Aug-2000 tim
This died again, but for an entirely different reason: it uses a
dict to map file pointers to process handles, and calls a dict
access function during popen.close(). But .close releases threads,
which left the internal popen code accessing the dict without a
valid thread state. The dict implementation changed so that&#39;s no
longer accepted. Fixed by creating a temporary thread state in the
guts of popen&#39;s close routine, and grabbing the global lock with
it for the duration]
[20-Aug-2000 tim
changed the popen2.py _test function to use the &quot;more&quot; cmd
when os.name == &quot;nt&quot;. This makes test_popen2 pass under
Win98SE.
HOWEVER, the Win98 &quot;more&quot; invents a leading newline out
of thin air, and I&#39;m not sure that the other Windows flavors
of &quot;more&quot; also do that.
So, somebody please try under other Windows flavors!
]
[still fails 15-Aug-2000 for me, on Win98 - tim
test test_popen2 crashed -- exceptions.AssertionError :
The problem is that the test uses &quot;cat&quot;, but there is
no such thing under Windows (unless you install it).
So it&#39;s the test that&#39;s broken here, not (necessarily)
the code.
]
test_winreg Win32 26-Jul-2000
[works 15-Aug-2000 for me, on Win98 - tim]
test_mmap Win32 26-Jul-2000
[believe that was fixed by Mark H.]
[works 15-Aug-2000 for me, on Win98 - tim]
test_longexp Win98+? 15-Aug-2000
[fails in release build,
passes in release build under verbose mode but doesn&#39;t
look like it should pass,
passes in debug build,
passes in debug build under verbose mode and looks like
it should pass
]
[18-Aug-2000, tim: can&#39;t reproduce, and nobody else
saw it. I believe there *is* a subtle bug in
regrtest.py when using -v, and I&#39;ll pursue that,
but can&#39;t provoke anything wrong with test_longexp
anymore; eyeballing Fred&#39;s changes didn&#39;t turn up
a suspect either
19-Aug-2000, tim: the &quot;subtle bug&quot; in regrtest.py -v is
actually a feature: -v masks *some* kinds of failures,
since it doesn&#39;t compare test output with the canned
output; this is what makes it say &quot;test passed&quot; even
in some cases where the test fails without -v
]
test_winreg2 Win32 26-Jul-2000
[20-Aug-2000 tim - the test has been removed from the project]
[19-Aug-2000 tim
This test will never work on Win98, because it&#39;s looking for
a part of registry that doesn&#39;t exist under W98.
The module (winreg.py) and this test case will be removed
before 2.0 for other reasons, though.
]
[still fails 15-Aug-2000 for me, on Win98 - tim
test test_winreg2 failed -- Writing: &#39;Test Failed: testHives&#39;,
expected: &#39;HKEY_PERFORMANCE_DATA\012&#39;
]
</pre></div>
</div>
</section>
<section id="open-items-completed-fixed">
<h2><a class="toc-backref" href="#open-items-completed-fixed" role="doc-backlink">Open items completed/fixed</a></h2>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>[4-Sep-2000 guido: Fredrik finished this on 1-Sep]
* PyErr_Format - Fredrik Lundh
Make this function safe from buffer overflows.
[4-Sep-2000 guido: Fred has added popen2, popen3 on 28-Sep]
Add popen2 support for Linux -- Fred Drake
[4-Sep-2000 guido: done on 1-Sep]
Deal with buffering problem with SocketServer
[04-Sep-2000 tim: done; installer runs; w9xpopen not an issue]
[01-Sep-2000 tim: make a prerelease available]
Windows ME: Don&#39;t know anything about it. Will the installer
even run? Does it need the w9xpopen hack?
[04-Sep-2000 tim: done; tested on several Windows flavors now]
[01-Sep-2000 tim: completed but untested except on Win98SE]
Windows installer: If HKLM isn&#39;t writable, back off to HKCU (so
Python can be installed on NT &amp; 2000 without admin privileges).
[01-Sep-200 tim - as Guido said, runtime code in posixmodule.c doesn&#39;t
call this on NT/2000, so no need to avoid installing it everywhere.
Added code to the installer *to* install it, though.]
Windows installer: Install w9xpopen.exe only under Win95/98.
[23-Aug-2000 jeremy - tim reports &quot;completed recently&quot;]
Windows: Look for registry info in HKCU before HKLM - Mark
Hammond.
[20-Aug-2000 tim - done]
Remove winreg.py and test_winreg2.py. Paul Prescod (the author)
now wants to make a registry API more like the MS .NET API. Unclear
whether that can be done in time for 2.0, but, regardless, if we
let winreg.py out the door we&#39;ll be stuck with it forever, and not
even Paul wants it anymore.
[24-Aug-2000 tim+guido - done]
Win98 Guido: popen is hanging on Guido, and even freezing the
whole machine. Was caused by Norton Antivirus 2000 (6.10.20) on
Windows 9x. Resolution: disable virus protection.
</pre></div>
</div>
</section>
<section id="accepted-and-completed">
<h2><a class="toc-backref" href="#accepted-and-completed" role="doc-backlink">Accepted and completed</a></h2>
<ul class="simple">
<li>Change meaning of x escapes - <a class="pep reference internal" href="../pep-0223/" title="PEP 223 Change the Meaning of \x Escapes">PEP 223</a> - Fredrik Lundh</li>
<li>Add U1234678 escapes in u”” strings - Fredrik Lundh</li>
<li>Support for opcode arguments &gt; <code class="docutils literal notranslate"><span class="pre">2**16</span></code> - Charles Waldman SF Patch
100893</li>
<li>“import as” - Thomas Wouters Extend the import and from …
import mechanism to enable importing a symbol as another name.
(Without adding a new keyword.)</li>
<li>List comprehensions - Skip Montanaro Tim Peters still needs to do
PEP.</li>
<li>Restore old os.path.commonprefix behavior Do we have test cases that
work on all platforms?</li>
<li>Tim OMalleys cookie module with good license</li>
<li>Lockstep iteration (“zip” function) - Barry Warsaw</li>
<li>SRE - Fredrik Lundh [at least I <strong>think</strong> its done, as of
15-Aug-2000 - tim]</li>
<li>Fix xrange printing behavior - Fred Drake Remove the tp_print
handler for the xrange type; it produced a list display instead of
xrange(…). The new code produces a minimal call to xrange(),
enclosed in (<code class="docutils literal notranslate"><span class="pre">...</span> <span class="pre">*</span> <span class="pre">N</span></code>) when N != 1. This makes the repr() more
human readable while making it do what reprs are advertised as
doing. It also makes the xrange objects obvious when working in the
interactive interpreter.</li>
<li>Extended print statement - Barry Warsaw <a class="pep reference internal" href="../pep-0214/" title="PEP 214 Extended Print Statement">PEP 214</a>
SF Patch #100970
<a class="reference external" href="http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=100970&amp;group_id=5470">http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=100970&amp;group_id=5470</a></li>
<li>interface to poll system call - Andrew Kuchling SF Patch 100852</li>
<li>Augmented assignment - Thomas Wouters Add += and family, plus Python
and C hooks, and API functions.</li>
<li>gettext.py module - Barry Warsaw</li>
</ul>
</section>
<section id="postponed">
<h2><a class="toc-backref" href="#postponed" role="doc-backlink">Postponed</a></h2>
<ul>
<li>Extended slicing on lists - Michael Hudson Make lists (and other
builtin types) handle extended slices.</li>
<li>Compression of Unicode database - Fredrik Lundh SF Patch 100899 At
least for 2.0b1. May be included in 2.0 as a bug fix.</li>
<li>Range literals - Thomas Wouters SF Patch 100902 We ended up having a
lot of doubt about the proposal.</li>
<li>Eliminated SET_LINENO opcode - Vladimir Marangozov Small
optimization achieved by using the code objects lnotab instead of
the SET_LINENO instruction. Uses code rewriting technique (that
Guidos frowns on) to support debugger, which uses SET_LINENO.<p><a class="reference external" href="http://starship.python.net/~vlad/lineno/">http://starship.python.net/~vlad/lineno/</a> for (working at the time)
patches</p>
<p>Discussions on python-dev:</p>
<ul class="simple">
<li><a class="reference external" href="http://www.python.org/pipermail/python-dev/2000-April/subject.html">http://www.python.org/pipermail/python-dev/2000-April/subject.html</a>
Subject: “Why do we need Traceback Objects?”</li>
<li><a class="reference external" href="http://www.python.org/pipermail/python-dev/1999-August/002252.html">http://www.python.org/pipermail/python-dev/1999-August/002252.html</a></li>
</ul>
</li>
<li>test harness for C code - Trent Mick</li>
</ul>
</section>
<section id="rejected">
<h2><a class="toc-backref" href="#rejected" role="doc-backlink">Rejected</a></h2>
<ul class="simple">
<li>indexing-for - Thomas Wouters Special syntax to give Python code
access to the loop-counter in for loops. (Without adding a new
keyword.)</li>
</ul>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0200.rst">https://github.com/python/peps/blob/main/peps/pep-0200.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0200.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#release-schedule">Release Schedule</a></li>
<li><a class="reference internal" href="#previous-milestones">Previous milestones</a></li>
<li><a class="reference internal" href="#what-is-release-candidate-1">What is release candidate 1?</a></li>
<li><a class="reference internal" href="#guidelines-for-submitting-patches-and-making-changes">Guidelines for submitting patches and making changes</a></li>
<li><a class="reference internal" href="#failing-test-cases-need-to-get-fixed">Failing test cases need to get fixed</a></li>
<li><a class="reference internal" href="#open-items-need-to-be-resolved-before-2-0-final-release">Open items Need to be resolved before 2.0 final release</a></li>
<li><a class="reference internal" href="#accepted-and-in-progress">Accepted and in progress</a></li>
<li><a class="reference internal" href="#open-proposed-but-not-accepted-or-rejected">Open: proposed but not accepted or rejected</a></li>
<li><a class="reference internal" href="#previously-failing-test-cases">Previously failing test cases</a></li>
<li><a class="reference internal" href="#open-items-completed-fixed">Open items completed/fixed</a></li>
<li><a class="reference internal" href="#accepted-and-completed">Accepted and completed</a></li>
<li><a class="reference internal" href="#postponed">Postponed</a></li>
<li><a class="reference internal" href="#rejected">Rejected</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0200.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

400
pep-0201/index.html Normal file
View File

@ -0,0 +1,400 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 201 Lockstep Iteration | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0201/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 201 Lockstep Iteration | peps.python.org'>
<meta property="og:description" content="This PEP describes the lockstep iteration proposal. This PEP tracks the status and ownership of this feature, slated for introduction in Python 2.0. It contains a description of the feature and outlines changes necessary to support the feature. This...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0201/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the lockstep iteration proposal. This PEP tracks the status and ownership of this feature, slated for introduction in Python 2.0. It contains a description of the feature and outlines changes necessary to support the feature. This...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 201</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 201 Lockstep Iteration</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">13-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.0</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">27-Jul-2000</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#lockstep-for-loops">Lockstep For-Loops</a></li>
<li><a class="reference internal" href="#the-proposed-solution">The Proposed Solution</a></li>
<li><a class="reference internal" href="#return-value">Return Value</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#bdfl-pronouncements">BDFL Pronouncements</a></li>
<li><a class="reference internal" href="#subsequent-change-to-zip">Subsequent Change to <code class="docutils literal notranslate"><span class="pre">zip()</span></code></a></li>
<li><a class="reference internal" href="#other-changes">Other Changes</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes the lockstep iteration proposal. This PEP tracks
the status and ownership of this feature, slated for introduction in
Python 2.0. It contains a description of the feature and outlines
changes necessary to support the feature. This PEP summarizes
discussions held in mailing list forums, and provides URLs for further
information, where appropriate. The CVS revision history of this file
contains the definitive historical record.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>Standard for-loops in Python iterate over every element in a sequence
until the sequence is exhausted <a class="footnote-reference brackets" href="#id3" id="id1">[1]</a>. However, for-loops iterate over
only a single sequence, and it is often desirable to loop over more
than one sequence in a lock-step fashion. In other words, in a way
such that the i-th iteration through the loop returns an object
containing the i-th element from each sequence.</p>
<p>The common idioms used to accomplish this are unintuitive. This PEP
proposes a standard way of performing such iterations by introducing a
new builtin function called <code class="docutils literal notranslate"><span class="pre">zip</span></code>.</p>
<p>While the primary motivation for zip() comes from lock-step iteration,
by implementing zip() as a built-in function, it has additional
utility in contexts other than for-loops.</p>
</section>
<section id="lockstep-for-loops">
<h2><a class="toc-backref" href="#lockstep-for-loops" role="doc-backlink">Lockstep For-Loops</a></h2>
<p>Lockstep for-loops are non-nested iterations over two or more
sequences, such that at each pass through the loop, one element from
each sequence is taken to compose the target. This behavior can
already be accomplished in Python through the use of the map() built-in
function:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">map</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span> <span class="nb">print</span> <span class="n">i</span>
<span class="gp">...</span>
<span class="go">(1, 4)</span>
<span class="go">(2, 5)</span>
<span class="go">(3, 6)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">map</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="go">[(1, 4), (2, 5), (3, 6)]</span>
</pre></div>
</div>
<p>The for-loop simply iterates over this list as normal.</p>
<p>While the map() idiom is a common one in Python, it has several
disadvantages:</p>
<ul>
<li>It is non-obvious to programmers without a functional programming
background.</li>
<li>The use of the magic <code class="docutils literal notranslate"><span class="pre">None</span></code> first argument is non-obvious.</li>
<li>It has arbitrary, often unintended, and inflexible semantics when
the lists are not of the same length: the shorter sequences are
padded with <code class="docutils literal notranslate"><span class="pre">None</span></code>:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span> <span class="o">=</span> <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">map</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span>
<span class="go">[(1, 4), (2, 5), (3, 6), (None, 7)]</span>
</pre></div>
</div>
</li>
</ul>
<p>For these reasons, several proposals were floated in the Python 2.0
beta time frame for syntactic support of lockstep for-loops. Here are
two suggestions:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">seq1</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">seq2</span><span class="p">:</span>
<span class="c1"># stuff</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">seq1</span><span class="p">,</span> <span class="n">seq2</span><span class="p">:</span>
<span class="c1"># stuff</span>
</pre></div>
</div>
<p>Neither of these forms would work, since they both already mean
something in Python and changing the meanings would break existing
code. All other suggestions for new syntax suffered the same problem,
or were in conflict with other another proposed feature called list
comprehensions (see <a class="pep reference internal" href="../pep-0202/" title="PEP 202 List Comprehensions">PEP 202</a>).</p>
</section>
<section id="the-proposed-solution">
<h2><a class="toc-backref" href="#the-proposed-solution" role="doc-backlink">The Proposed Solution</a></h2>
<p>The proposed solution is to introduce a new built-in sequence
generator function, available in the <code class="docutils literal notranslate"><span class="pre">__builtin__</span></code> module. This
function is to be called <code class="docutils literal notranslate"><span class="pre">zip</span></code> and has the following signature:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">zip</span><span class="p">(</span><span class="n">seqa</span><span class="p">,</span> <span class="p">[</span><span class="n">seqb</span><span class="p">,</span> <span class="p">[</span><span class="o">...</span><span class="p">]])</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">zip()</span></code> takes one or more sequences and weaves their elements
together, just as <code class="docutils literal notranslate"><span class="pre">map(None,</span> <span class="pre">...)</span></code> does with sequences of equal
length. The weaving stops when the shortest sequence is exhausted.</p>
</section>
<section id="return-value">
<h2><a class="toc-backref" href="#return-value" role="doc-backlink">Return Value</a></h2>
<p><code class="docutils literal notranslate"><span class="pre">zip()</span></code> returns a real Python list, the same way <code class="docutils literal notranslate"><span class="pre">map()</span></code> does.</p>
</section>
<section id="examples">
<h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2>
<p>Here are some examples, based on the reference implementation below:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span> <span class="o">=</span> <span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">11</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">13</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">zip</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="go">[(1, 5), (2, 6), (3, 7), (4, 8)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">zip</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
<span class="go">[(1, 12), (2, 13)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">zip</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
<span class="go">[(1, 5, 9, 12), (2, 6, 10, 13)]</span>
</pre></div>
</div>
<p>Note that when the sequences are of the same length, <code class="docutils literal notranslate"><span class="pre">zip()</span></code> is
reversible:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="nb">zip</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">y</span> <span class="o">=</span> <span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">x</span><span class="p">)</span> <span class="c1"># alternatively, apply(zip, x)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">z</span> <span class="o">=</span> <span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">y</span><span class="p">)</span> <span class="c1"># alternatively, apply(zip, y)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">x</span>
<span class="go">[(1, 4), (2, 5), (3, 6)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">y</span>
<span class="go">[(1, 2, 3), (4, 5, 6)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">z</span>
<span class="go">[(1, 4), (2, 5), (3, 6)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">==</span> <span class="n">z</span>
<span class="go">1</span>
</pre></div>
</div>
<p>It is not possible to reverse zip this way when the sequences are not
all the same length.</p>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>Here is a reference implementation, in Python of the zip() built-in
function. This will be replaced with a C implementation after final
approval:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">zip</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">args</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">&#39;zip() expects one or more sequence arguments&#39;</span><span class="p">)</span>
<span class="n">ret</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">item</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
<span class="n">item</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
<span class="n">ret</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">tuple</span><span class="p">(</span><span class="n">item</span><span class="p">))</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span>
<span class="k">return</span> <span class="n">ret</span>
</pre></div>
</div>
</section>
<section id="bdfl-pronouncements">
<h2><a class="toc-backref" href="#bdfl-pronouncements" role="doc-backlink">BDFL Pronouncements</a></h2>
<p>Note: the BDFL refers to Guido van Rossum, Pythons Benevolent
Dictator For Life.</p>
<ul class="simple">
<li>The functions name. An earlier version of this PEP included an
open issue listing 20+ proposed alternative names to <code class="docutils literal notranslate"><span class="pre">zip()</span></code>. In
the face of no overwhelmingly better choice, the BDFL strongly
prefers <code class="docutils literal notranslate"><span class="pre">zip()</span></code> due to its Haskell <a class="footnote-reference brackets" href="#id4" id="id2">[2]</a> heritage. See version 1.7
of this PEP for the list of alternatives.</li>
<li><code class="docutils literal notranslate"><span class="pre">zip()</span></code> shall be a built-in function.</li>
<li>Optional padding. An earlier version of this PEP proposed an
optional <code class="docutils literal notranslate"><span class="pre">pad</span></code> keyword argument, which would be used when the
argument sequences were not the same length. This is similar
behavior to the <code class="docutils literal notranslate"><span class="pre">map(None,</span> <span class="pre">...)</span></code> semantics except that the user
would be able to specify pad object. This has been rejected by the
BDFL in favor of always truncating to the shortest sequence, because
of the KISS principle. If theres a true need, it is easier to add
later. If it is not needed, it would still be impossible to delete
it in the future.</li>
<li>Lazy evaluation. An earlier version of this PEP proposed that
<code class="docutils literal notranslate"><span class="pre">zip()</span></code> return a built-in object that performed lazy evaluation
using <code class="docutils literal notranslate"><span class="pre">__getitem__()</span></code> protocol. This has been strongly rejected
by the BDFL in favor of returning a real Python list. If lazy
evaluation is desired in the future, the BDFL suggests an <code class="docutils literal notranslate"><span class="pre">xzip()</span></code>
function be added.</li>
<li><code class="docutils literal notranslate"><span class="pre">zip()</span></code> with no arguments. the BDFL strongly prefers this raise a
TypeError exception.</li>
<li><code class="docutils literal notranslate"><span class="pre">zip()</span></code> with one argument. the BDFL strongly prefers that this
return a list of 1-tuples.</li>
<li>Inner and outer container control. An earlier version of this PEP
contains a rather lengthy discussion on a feature that some people
wanted, namely the ability to control what the inner and outer
container types were (they are tuples and list respectively in this
version of the PEP). Given the simplified API and implementation,
this elaboration is rejected. For a more detailed analysis, see
version 1.7 of this PEP.</li>
</ul>
</section>
<section id="subsequent-change-to-zip">
<h2><a class="toc-backref" href="#subsequent-change-to-zip" role="doc-backlink">Subsequent Change to <code class="docutils literal notranslate"><span class="pre">zip()</span></code></a></h2>
<p>In Python 2.4, zip() with no arguments was modified to return an empty
list rather than raising a TypeError exception. The rationale for the
original behavior was that the absence of arguments was thought to
indicate a programming error. However, that thinking did not
anticipate the use of zip() with the <code class="docutils literal notranslate"><span class="pre">*</span></code> operator for unpacking
variable length argument lists. For example, the inverse of zip could
be defined as: <code class="docutils literal notranslate"><span class="pre">unzip</span> <span class="pre">=</span> <span class="pre">lambda</span> <span class="pre">s:</span> <span class="pre">zip(*s)</span></code>. That transformation
also defines a matrix transpose or an equivalent row/column swap for
tables defined as lists of tuples. The latter transformation is
commonly used when reading data files with records as rows and fields
as columns. For example, the code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">date</span><span class="p">,</span> <span class="n">rain</span><span class="p">,</span> <span class="n">high</span><span class="p">,</span> <span class="n">low</span> <span class="o">=</span> <span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">csv</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="n">file</span><span class="p">(</span><span class="s2">&quot;weather.csv&quot;</span><span class="p">)))</span>
</pre></div>
</div>
<p>rearranges columnar data so that each field is collected into
individual tuples for straightforward looping and summarization:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="s2">&quot;Total rainfall&quot;</span><span class="p">,</span> <span class="nb">sum</span><span class="p">(</span><span class="n">rain</span><span class="p">)</span>
</pre></div>
</div>
<p>Using <code class="docutils literal notranslate"><span class="pre">zip(*args)</span></code> is more easily coded if <code class="docutils literal notranslate"><span class="pre">zip(*[])</span></code> is handled
as an allowable case rather than an exception. This is especially
helpful when data is either built up from or recursed down to a null
case with no records.</p>
<p>Seeing this possibility, the BDFL agreed (with some misgivings) to
have the behavior changed for Py2.4.</p>
</section>
<section id="other-changes">
<h2><a class="toc-backref" href="#other-changes" role="doc-backlink">Other Changes</a></h2>
<ul>
<li>The <code class="docutils literal notranslate"><span class="pre">xzip()</span></code> function discussed above was implemented in Py2.3 in
the <code class="docutils literal notranslate"><span class="pre">itertools</span></code> module as <code class="docutils literal notranslate"><span class="pre">itertools.izip()</span></code>. This function
provides lazy behavior, consuming single elements and producing a
single tuple on each pass. The “just-in-time” style saves memory
and runs faster than its list based counterpart, <code class="docutils literal notranslate"><span class="pre">zip()</span></code>.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">itertools</span></code> module also added <code class="docutils literal notranslate"><span class="pre">itertools.repeat()</span></code> and
<code class="docutils literal notranslate"><span class="pre">itertools.chain()</span></code>. These tools can be used together to pad
sequences with <code class="docutils literal notranslate"><span class="pre">None</span></code> (to match the behavior of <code class="docutils literal notranslate"><span class="pre">map(None,</span>
<span class="pre">seqn)</span></code>):<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">zip</span><span class="p">(</span><span class="n">firstseq</span><span class="p">,</span> <span class="n">chain</span><span class="p">(</span><span class="n">secondseq</span><span class="p">,</span> <span class="n">repeat</span><span class="p">(</span><span class="kc">None</span><span class="p">)))</span>
</pre></div>
</div>
</li>
</ul>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id3" role="doc-footnote">
<dt class="label" id="id3">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://docs.python.org/reference/compound_stmts.html#for">http://docs.python.org/reference/compound_stmts.html#for</a></aside>
<aside class="footnote brackets" id="id4" role="doc-footnote">
<dt class="label" id="id4">[<a href="#id2">2</a>]</dt>
<dd><a class="reference external" href="http://www.haskell.org/onlinereport/standard-prelude.html#$vzip">http://www.haskell.org/onlinereport/standard-prelude.html#$vzip</a></aside>
</aside>
<p>Greg Wilsons questionnaire on proposed syntax to some CS grad students
<a class="reference external" href="http://www.python.org/pipermail/python-dev/2000-July/013139.html">http://www.python.org/pipermail/python-dev/2000-July/013139.html</a></p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0201.rst">https://github.com/python/peps/blob/main/peps/pep-0201.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0201.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#lockstep-for-loops">Lockstep For-Loops</a></li>
<li><a class="reference internal" href="#the-proposed-solution">The Proposed Solution</a></li>
<li><a class="reference internal" href="#return-value">Return Value</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#bdfl-pronouncements">BDFL Pronouncements</a></li>
<li><a class="reference internal" href="#subsequent-change-to-zip">Subsequent Change to <code class="docutils literal notranslate"><span class="pre">zip()</span></code></a></li>
<li><a class="reference internal" href="#other-changes">Other Changes</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0201.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

203
pep-0202/index.html Normal file
View File

@ -0,0 +1,203 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 202 List Comprehensions | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0202/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 202 List Comprehensions | peps.python.org'>
<meta property="og:description" content="This PEP describes a proposed syntactical extension to Python, list comprehensions.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0202/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes a proposed syntactical extension to Python, list comprehensions.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 202</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 202 List Comprehensions</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">13-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.0</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#the-proposed-solution">The Proposed Solution</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#bdfl-pronouncements">BDFL Pronouncements</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes a proposed syntactical extension to Python, list
comprehensions.</p>
</section>
<section id="the-proposed-solution">
<h2><a class="toc-backref" href="#the-proposed-solution" role="doc-backlink">The Proposed Solution</a></h2>
<p>It is proposed to allow conditional construction of list literals using for and
if clauses. They would nest in the same way for loops and if statements nest
now.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>List comprehensions provide a more concise way to create lists in situations
where <code class="docutils literal notranslate"><span class="pre">map()</span></code> and <code class="docutils literal notranslate"><span class="pre">filter()</span></code> and/or nested loops would currently be used.</p>
</section>
<section id="examples">
<h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">)]</span>
<span class="go">[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span> <span class="k">if</span> <span class="n">i</span><span class="o">%</span><span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">]</span>
<span class="go">[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fruit</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;Apples&quot;</span><span class="p">,</span> <span class="s2">&quot;Peaches&quot;</span><span class="p">,</span> <span class="s2">&quot;Pears&quot;</span><span class="p">,</span> <span class="s2">&quot;Bananas&quot;</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span> <span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">nums</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fruit</span><span class="p">]</span>
<span class="go">[(1, &#39;Apples&#39;), (1, &#39;Peaches&#39;), (1, &#39;Pears&#39;), (1, &#39;Bananas&#39;),</span>
<span class="go"> (2, &#39;Apples&#39;), (2, &#39;Peaches&#39;), (2, &#39;Pears&#39;), (2, &#39;Bananas&#39;),</span>
<span class="go"> (3, &#39;Apples&#39;), (3, &#39;Peaches&#39;), (3, &#39;Pears&#39;), (3, &#39;Bananas&#39;),</span>
<span class="go"> (4, &#39;Apples&#39;), (4, &#39;Peaches&#39;), (4, &#39;Pears&#39;), (4, &#39;Bananas&#39;)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span> <span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">nums</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fruit</span> <span class="k">if</span> <span class="n">f</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">&quot;P&quot;</span><span class="p">]</span>
<span class="go">[(1, &#39;Peaches&#39;), (1, &#39;Pears&#39;),</span>
<span class="go"> (2, &#39;Peaches&#39;), (2, &#39;Pears&#39;),</span>
<span class="go"> (3, &#39;Peaches&#39;), (3, &#39;Pears&#39;),</span>
<span class="go"> (4, &#39;Peaches&#39;), (4, &#39;Pears&#39;)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span> <span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">nums</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fruit</span> <span class="k">if</span> <span class="n">f</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">&quot;P&quot;</span> <span class="k">if</span> <span class="n">i</span><span class="o">%</span><span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">]</span>
<span class="go">[(1, &#39;Peaches&#39;), (1, &#39;Pears&#39;), (3, &#39;Peaches&#39;), (3, &#39;Pears&#39;)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">nums</span><span class="p">,</span> <span class="n">fruit</span><span class="p">)</span> <span class="k">if</span> <span class="n">i</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">%</span><span class="mi">2</span><span class="o">==</span><span class="mi">0</span><span class="p">]</span>
<span class="go">[(2, &#39;Peaches&#39;), (4, &#39;Bananas&#39;)]</span>
</pre></div>
</div>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>List comprehensions become part of the Python language with release 2.0,
documented in <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>.</p>
</section>
<section id="bdfl-pronouncements">
<h2><a class="toc-backref" href="#bdfl-pronouncements" role="doc-backlink">BDFL Pronouncements</a></h2>
<ul class="simple">
<li>The syntax proposed above is the Right One.</li>
<li>The form <code class="docutils literal notranslate"><span class="pre">[x,</span> <span class="pre">y</span> <span class="pre">for</span> <span class="pre">...]</span></code> is disallowed; one is required to write
<code class="docutils literal notranslate"><span class="pre">[(x,</span> <span class="pre">y)</span> <span class="pre">for</span> <span class="pre">...]</span></code>.</li>
<li>The form <code class="docutils literal notranslate"><span class="pre">[...</span> <span class="pre">for</span> <span class="pre">x...</span> <span class="pre">for</span> <span class="pre">y...]</span></code> nests, with the last index
varying fastest, just like nested for loops.</li>
</ul>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://docs.python.org/reference/expressions.html#list-displays">http://docs.python.org/reference/expressions.html#list-displays</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0202.rst">https://github.com/python/peps/blob/main/peps/pep-0202.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0202.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#the-proposed-solution">The Proposed Solution</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#bdfl-pronouncements">BDFL Pronouncements</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0202.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

421
pep-0203/index.html Normal file
View File

@ -0,0 +1,421 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 203 Augmented Assignments | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0203/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 203 Augmented Assignments | peps.python.org'>
<meta property="og:description" content="This PEP describes the augmented assignment proposal for Python 2.0. This PEP tracks the status and ownership of this feature, slated for introduction in Python 2.0. It contains a description of the feature and outlines changes necessary to support th...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0203/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the augmented assignment proposal for Python 2.0. This PEP tracks the status and ownership of this feature, slated for introduction in Python 2.0. It contains a description of the feature and outlines changes necessary to support th...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 203</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 203 Augmented Assignments</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Thomas Wouters &lt;thomas&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">13-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.0</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">14-Aug-2000</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#proposed-semantics">Proposed Semantics</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#new-methods">New methods</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes the <em>augmented assignment</em> proposal for Python 2.0. This
PEP tracks the status and ownership of this feature, slated for introduction
in Python 2.0. It contains a description of the feature and outlines changes
necessary to support the feature. This PEP summarizes discussions held in
mailing list forums <a class="footnote-reference brackets" href="#id3" id="id1">[1]</a>, and provides URLs for further information where
appropriate. The CVS revision history of this file contains the definitive
historical record.</p>
</section>
<section id="proposed-semantics">
<h2><a class="toc-backref" href="#proposed-semantics" role="doc-backlink">Proposed Semantics</a></h2>
<p>The proposed patch that adds augmented assignment to Python introduces the
following new operators:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">+=</span> <span class="o">-=</span> <span class="o">*=</span> <span class="o">/=</span> <span class="o">%=</span> <span class="o">**=</span> <span class="o">&lt;&lt;=</span> <span class="o">&gt;&gt;=</span> <span class="o">&amp;=</span> <span class="o">^=</span> <span class="o">|=</span>
</pre></div>
</div>
<p>They implement the same operator as their normal binary form, except that the
operation is done <em>in-place</em> when the left-hand side object supports it, and
that the left-hand side is only evaluated once.</p>
<p>They truly behave as augmented assignment, in that they perform all of the
normal load and store operations, in addition to the binary operation they are
intended to do. So, given the expression:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">+=</span> <span class="n">y</span>
</pre></div>
</div>
<p>The object <code class="docutils literal notranslate"><span class="pre">x</span></code> is loaded, then <code class="docutils literal notranslate"><span class="pre">y</span></code> is added to it, and the resulting
object is stored back in the original place. The precise action performed on
the two arguments depends on the type of <code class="docutils literal notranslate"><span class="pre">x</span></code>, and possibly of <code class="docutils literal notranslate"><span class="pre">y</span></code>.</p>
<p>The idea behind augmented assignment in Python is that it isnt just an easier
way to write the common practice of storing the result of a binary operation
in its left-hand operand, but also a way for the left-hand operand in question
to know that it should operate <em>on itself</em>, rather than creating a modified
copy of itself.</p>
<p>To make this possible, a number of new <em>hooks</em> are added to Python classes and
C extension types, which are called when the object in question is used as the
left hand side of an augmented assignment operation. If the class or type
does not implement the <em>in-place</em> hooks, the normal hooks for the particular
binary operation are used.</p>
<p>So, given an instance object <code class="docutils literal notranslate"><span class="pre">x</span></code>, the expression:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">+=</span> <span class="n">y</span>
</pre></div>
</div>
<p>tries to call <code class="docutils literal notranslate"><span class="pre">x.__iadd__(y)</span></code>, which is the <em>in-place</em> variant of
<code class="docutils literal notranslate"><span class="pre">__add__</span></code> . If <code class="docutils literal notranslate"><span class="pre">__iadd__</span></code> is not present, <code class="docutils literal notranslate"><span class="pre">x.__add__(y)</span></code> is attempted,
and finally <code class="docutils literal notranslate"><span class="pre">y.__radd__(x)</span></code> if <code class="docutils literal notranslate"><span class="pre">__add__</span></code> is missing too. There is no
<em>right-hand-side</em> variant of <code class="docutils literal notranslate"><span class="pre">__iadd__</span></code>, because that would require for
<code class="docutils literal notranslate"><span class="pre">y</span></code> to know how to in-place modify <code class="docutils literal notranslate"><span class="pre">x</span></code>, which is unsafe to say the least.
The <code class="docutils literal notranslate"><span class="pre">__iadd__</span></code> hook should behave similar to <code class="docutils literal notranslate"><span class="pre">__add__</span></code>, returning the
result of the operation (which could be <code class="docutils literal notranslate"><span class="pre">self</span></code>) which is to be assigned to
the variable <code class="docutils literal notranslate"><span class="pre">x</span></code>.</p>
<p>For C extension types, the <em>hooks</em> are members of the <code class="docutils literal notranslate"><span class="pre">PyNumberMethods</span></code> and
<code class="docutils literal notranslate"><span class="pre">PySequenceMethods</span></code> structures. Some special semantics apply to make the
use of these methods, and the mixing of Python instance objects and C types,
as unsurprising as possible.</p>
<p>In the generic case of <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">&lt;augop&gt;</span> <span class="pre">y</span></code> (or a similar case using the
<code class="docutils literal notranslate"><span class="pre">PyNumber_InPlace</span></code> API functions) the principal object being operated on is
<code class="docutils literal notranslate"><span class="pre">x</span></code>. This differs from normal binary operations, where <code class="docutils literal notranslate"><span class="pre">x</span></code> and <code class="docutils literal notranslate"><span class="pre">y</span></code>
could be considered <em>co-operating</em>, because unlike in binary operations, the
operands in an in-place operation cannot be swapped. However, in-place
operations do fall back to normal binary operations when in-place modification
is not supported, resulting in the following rules:</p>
<ul>
<li>If the left-hand object (<code class="docutils literal notranslate"><span class="pre">x</span></code>) is an instance object, and it has a
<code class="docutils literal notranslate"><span class="pre">__coerce__</span></code> method, call that function with <code class="docutils literal notranslate"><span class="pre">y</span></code> as the argument. If
coercion succeeds, and the resulting left-hand object is a different object
than <code class="docutils literal notranslate"><span class="pre">x</span></code>, stop processing it as in-place and call the appropriate function
for the normal binary operation, with the coerced <code class="docutils literal notranslate"><span class="pre">x</span></code> and <code class="docutils literal notranslate"><span class="pre">y</span></code> as
arguments. The result of the operation is whatever that function returns.<p>If coercion does not yield a different object for <code class="docutils literal notranslate"><span class="pre">x</span></code>, or <code class="docutils literal notranslate"><span class="pre">x</span></code> does not
define a <code class="docutils literal notranslate"><span class="pre">__coerce__</span></code> method, and <code class="docutils literal notranslate"><span class="pre">x</span></code> has the appropriate <code class="docutils literal notranslate"><span class="pre">__ihook__</span></code>
for this operation, call that method with <code class="docutils literal notranslate"><span class="pre">y</span></code> as the argument, and the
result of the operation is whatever that method returns.</p>
</li>
<li>Otherwise, if the left-hand object is not an instance object, but its type
does define the in-place function for this operation, call that function
with <code class="docutils literal notranslate"><span class="pre">x</span></code> and <code class="docutils literal notranslate"><span class="pre">y</span></code> as the arguments, and the result of the operation is
whatever that function returns.<p>Note that no coercion on either <code class="docutils literal notranslate"><span class="pre">x</span></code> or <code class="docutils literal notranslate"><span class="pre">y</span></code> is done in this case, and
its perfectly valid for a C type to receive an instance object as the
second argument; that is something that cannot happen with normal binary
operations.</p>
</li>
<li>Otherwise, process it exactly as a normal binary operation (not in-place),
including argument coercion. In short, if either argument is an instance
object, resolve the operation through <code class="docutils literal notranslate"><span class="pre">__coerce__</span></code>, <code class="docutils literal notranslate"><span class="pre">__hook__</span></code> and
<code class="docutils literal notranslate"><span class="pre">__rhook__</span></code>. Otherwise, both objects are C types, and they are coerced
and passed to the appropriate function.</li>
<li>If no way to process the operation can be found, raise a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> with
an error message specific to the operation.</li>
<li>Some special casing exists to account for the case of <code class="docutils literal notranslate"><span class="pre">+</span></code> and <code class="docutils literal notranslate"><span class="pre">*</span></code>,
which have a special meaning for sequences: for <code class="docutils literal notranslate"><span class="pre">+</span></code>, sequence
concatenation, no coercion what so ever is done if a C type defines
<code class="docutils literal notranslate"><span class="pre">sq_concat</span></code> or <code class="docutils literal notranslate"><span class="pre">sq_inplace_concat</span></code>. For <code class="docutils literal notranslate"><span class="pre">*</span></code>, sequence repeating,
<code class="docutils literal notranslate"><span class="pre">y</span></code> is converted to a C integer before calling either
<code class="docutils literal notranslate"><span class="pre">sq_inplace_repeat</span></code> and <code class="docutils literal notranslate"><span class="pre">sq_repeat</span></code>. This is done even if <code class="docutils literal notranslate"><span class="pre">y</span></code> is an
instance, though not if <code class="docutils literal notranslate"><span class="pre">x</span></code> is an instance.</li>
</ul>
<p>The in-place function should always return a new reference, either to the
old <code class="docutils literal notranslate"><span class="pre">x</span></code> object if the operation was indeed performed in-place, or to a new
object.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>There are two main reasons for adding this feature to Python: simplicity of
expression, and support for in-place operations. The end result is a tradeoff
between simplicity of syntax and simplicity of expression; like most new
features, augmented assignment doesnt add anything that was previously
impossible. It merely makes these things easier to do.</p>
<p>Adding augmented assignment will make Pythons syntax more complex. Instead
of a single assignment operation, there are now twelve assignment operations,
eleven of which also perform a binary operation. However, these eleven new
forms of assignment are easy to understand as the coupling between assignment
and the binary operation, and they require no large conceptual leap to
understand. Furthermore, languages that do have augmented assignment have
shown that they are a popular, much used feature. Expressions of the form:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&lt;</span><span class="n">x</span><span class="o">&gt;</span> <span class="o">=</span> <span class="o">&lt;</span><span class="n">x</span><span class="o">&gt;</span> <span class="o">&lt;</span><span class="n">operator</span><span class="o">&gt;</span> <span class="o">&lt;</span><span class="n">y</span><span class="o">&gt;</span>
</pre></div>
</div>
<p>are common enough in those languages to make the extra syntax worthwhile, and
Python does not have significantly fewer of those expressions. Quite the
opposite, in fact, since in Python you can also concatenate lists with a
binary operator, something that is done quite frequently. Writing the above
expression as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&lt;</span><span class="n">x</span><span class="o">&gt;</span> <span class="o">&lt;</span><span class="n">operator</span><span class="o">&gt;=</span> <span class="o">&lt;</span><span class="n">y</span><span class="o">&gt;</span>
</pre></div>
</div>
<p>is both more readable and less error prone, because it is instantly obvious to
the reader that it is <code class="docutils literal notranslate"><span class="pre">&lt;x&gt;</span></code> that is being changed, and not <code class="docutils literal notranslate"><span class="pre">&lt;x&gt;</span></code> that is
being replaced by something almost, but not quite, entirely unlike <code class="docutils literal notranslate"><span class="pre">&lt;x&gt;</span></code>.</p>
<p>The new in-place operations are especially useful to matrix calculation and
other applications that require large objects. In order to efficiently deal
with the available program memory, such packages cannot blindly use the
current binary operations. Because these operations always create a new
object, adding a single item to an existing (large) object would result in
copying the entire object (which may cause the application to run out of
memory), add the single item, and then possibly delete the original object,
depending on reference count.</p>
<p>To work around this problem, the packages currently have to use methods or
functions to modify an object in-place, which is definitely less readable than
an augmented assignment expression. Augmented assignment wont solve all the
problems for these packages, since some operations cannot be expressed in the
limited set of binary operators to start with, but it is a start. <a class="pep reference internal" href="../pep-0211/" title="PEP 211 Adding A New Outer Product Operator">PEP 211</a>
is looking at adding new operators.</p>
</section>
<section id="new-methods">
<h2><a class="toc-backref" href="#new-methods" role="doc-backlink">New methods</a></h2>
<p>The proposed implementation adds the following 11 possible <em>hooks</em> which
Python classes can implement to overload the augmented assignment operations:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="fm">__iadd__</span>
<span class="fm">__isub__</span>
<span class="fm">__imul__</span>
<span class="n">__idiv__</span>
<span class="fm">__imod__</span>
<span class="fm">__ipow__</span>
<span class="fm">__ilshift__</span>
<span class="fm">__irshift__</span>
<span class="fm">__iand__</span>
<span class="fm">__ixor__</span>
<span class="fm">__ior__</span>
</pre></div>
</div>
<p>The <em>i</em> in <code class="docutils literal notranslate"><span class="pre">__iadd__</span></code> stands for <em>in-place</em>.</p>
<p>For C extension types, the following struct members are added.</p>
<p>To <code class="docutils literal notranslate"><span class="pre">PyNumberMethods</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">binaryfunc</span> <span class="n">nb_inplace_add</span><span class="p">;</span>
<span class="n">binaryfunc</span> <span class="n">nb_inplace_subtract</span><span class="p">;</span>
<span class="n">binaryfunc</span> <span class="n">nb_inplace_multiply</span><span class="p">;</span>
<span class="n">binaryfunc</span> <span class="n">nb_inplace_divide</span><span class="p">;</span>
<span class="n">binaryfunc</span> <span class="n">nb_inplace_remainder</span><span class="p">;</span>
<span class="n">binaryfunc</span> <span class="n">nb_inplace_power</span><span class="p">;</span>
<span class="n">binaryfunc</span> <span class="n">nb_inplace_lshift</span><span class="p">;</span>
<span class="n">binaryfunc</span> <span class="n">nb_inplace_rshift</span><span class="p">;</span>
<span class="n">binaryfunc</span> <span class="n">nb_inplace_and</span><span class="p">;</span>
<span class="n">binaryfunc</span> <span class="n">nb_inplace_xor</span><span class="p">;</span>
<span class="n">binaryfunc</span> <span class="n">nb_inplace_or</span><span class="p">;</span>
</pre></div>
</div>
<p>To <code class="docutils literal notranslate"><span class="pre">PySequenceMethods</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">binaryfunc</span> <span class="n">sq_inplace_concat</span><span class="p">;</span>
<span class="n">intargfunc</span> <span class="n">sq_inplace_repeat</span><span class="p">;</span>
</pre></div>
</div>
<p>In order to keep binary compatibility, the <code class="docutils literal notranslate"><span class="pre">tp_flags</span></code> TypeObject member is
used to determine whether the TypeObject in question has allocated room for
these slots. Until a clean break in binary compatibility is made (which may
or may not happen before 2.0) code that wants to use one of the new struct
members must first check that they are available with the
<code class="docutils literal notranslate"><span class="pre">PyType_HasFeature()</span></code> macro:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">PyType_HasFeature</span><span class="p">(</span><span class="n">x</span><span class="o">-&gt;</span><span class="n">ob_type</span><span class="p">,</span> <span class="n">Py_TPFLAGS_HAVE_INPLACE_OPS</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
<span class="n">x</span><span class="o">-&gt;</span><span class="n">ob_type</span><span class="o">-&gt;</span><span class="n">tp_as_number</span> <span class="o">&amp;&amp;</span> <span class="n">x</span><span class="o">-&gt;</span><span class="n">ob_type</span><span class="o">-&gt;</span><span class="n">tp_as_number</span><span class="o">-&gt;</span><span class="n">nb_inplace_add</span><span class="p">)</span> <span class="p">{</span>
<span class="o">/*</span> <span class="o">...</span> <span class="o">*/</span>
</pre></div>
</div>
<p>This check must be made even before testing the method slots for <code class="docutils literal notranslate"><span class="pre">NULL</span></code>
values! The macro only tests whether the slots are available, not whether
they are filled with methods or not.</p>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>The current implementation of augmented assignment <a class="footnote-reference brackets" href="#id4" id="id2">[2]</a> adds, in addition to
the methods and slots already covered, 13 new bytecodes and 13 new API
functions.</p>
<p>The API functions are simply in-place versions of the current binary-operation
API functions:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyNumber_InPlaceAdd</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PyNumber_InPlaceSubtract</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PyNumber_InPlaceMultiply</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PyNumber_InPlaceDivide</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PyNumber_InPlaceRemainder</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PyNumber_InPlacePower</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PyNumber_InPlaceLshift</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PyNumber_InPlaceRshift</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PyNumber_InPlaceAnd</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PyNumber_InPlaceXor</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PyNumber_InPlaceOr</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PySequence_InPlaceConcat</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o1</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">o2</span><span class="p">);</span>
<span class="n">PySequence_InPlaceRepeat</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">o</span><span class="p">,</span> <span class="nb">int</span> <span class="n">count</span><span class="p">);</span>
</pre></div>
</div>
<p>They call either the Python class hooks (if either of the objects is a Python
class instance) or the C types number or sequence methods.</p>
<p>The new bytecodes are:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">INPLACE_ADD</span>
<span class="n">INPLACE_SUBTRACT</span>
<span class="n">INPLACE_MULTIPLY</span>
<span class="n">INPLACE_DIVIDE</span>
<span class="n">INPLACE_REMAINDER</span>
<span class="n">INPLACE_POWER</span>
<span class="n">INPLACE_LEFTSHIFT</span>
<span class="n">INPLACE_RIGHTSHIFT</span>
<span class="n">INPLACE_AND</span>
<span class="n">INPLACE_XOR</span>
<span class="n">INPLACE_OR</span>
<span class="n">ROT_FOUR</span>
<span class="n">DUP_TOPX</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">INPLACE_*</span></code> bytecodes mirror the <code class="docutils literal notranslate"><span class="pre">BINARY_*</span></code> bytecodes, except that
they are implemented as calls to the <code class="docutils literal notranslate"><span class="pre">InPlace</span></code> API functions. The other two
bytecodes are <em>utility</em> bytecodes: <code class="docutils literal notranslate"><span class="pre">ROT_FOUR</span></code> behaves like <code class="docutils literal notranslate"><span class="pre">ROT_THREE</span></code>
except that the four topmost stack items are rotated.</p>
<p><code class="docutils literal notranslate"><span class="pre">DUP_TOPX</span></code> is a bytecode that takes a single argument, which should be an
integer between 1 and 5 (inclusive) which is the number of items to duplicate
in one block. Given a stack like this (where the right side of the list is
the <em>top</em> of the stack):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">DUP_TOPX</span> <span class="pre">3</span></code> would duplicate the top 3 items, resulting in this stack:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">DUP_TOPX</span></code> with an argument of 1 is the same as <code class="docutils literal notranslate"><span class="pre">DUP_TOP</span></code>. The limit of 5
is purely an implementation limit . The implementation of augmented
assignment requires only <code class="docutils literal notranslate"><span class="pre">DUP_TOPX</span></code> with an argument of 2 and 3, and could
do without this new opcode at the cost of a fair number of <code class="docutils literal notranslate"><span class="pre">DUP_TOP</span></code> and
<code class="docutils literal notranslate"><span class="pre">ROT_*</span></code>.</p>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">PyNumber_InPlace</span></code> API is only a subset of the normal <code class="docutils literal notranslate"><span class="pre">PyNumber</span></code> API:
only those functions that are required to support the augmented assignment
syntax are included. If other in-place API functions are needed, they can be
added later.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">DUP_TOPX</span></code> bytecode is a conveniency bytecode, and is not actually
necessary. It should be considered whether this bytecode is worth having.
There seems to be no other possible use for this bytecode at this time.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id3" role="doc-footnote">
<dt class="label" id="id3">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://www.python.org/pipermail/python-list/2000-June/059556.html">http://www.python.org/pipermail/python-list/2000-June/059556.html</a></aside>
<aside class="footnote brackets" id="id4" role="doc-footnote">
<dt class="label" id="id4">[<a href="#id2">2</a>]</dt>
<dd><a class="reference external" href="http://sourceforge.net/patch?func=detailpatch&amp;patch_id=100699&amp;group_id=5470">http://sourceforge.net/patch?func=detailpatch&amp;patch_id=100699&amp;group_id=5470</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0203.rst">https://github.com/python/peps/blob/main/peps/pep-0203.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0203.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#proposed-semantics">Proposed Semantics</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#new-methods">New methods</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0203.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

402
pep-0204/index.html Normal file
View File

@ -0,0 +1,402 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 204 Range Literals | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0204/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 204 Range Literals | peps.python.org'>
<meta property="og:description" content="This PEP describes the “range literal” proposal for Python 2.0. This PEP tracks the status and ownership of this feature, slated for introduction in Python 2.0. It contains a description of the feature and outlines changes necessary to support the feat...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0204/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the “range literal” proposal for Python 2.0. This PEP tracks the status and ownership of this feature, slated for introduction in Python 2.0. It contains a description of the feature and outlines changes necessary to support the feat...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 204</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 204 Range Literals</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Thomas Wouters &lt;thomas&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">14-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.0</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#list-ranges">List ranges</a></li>
<li><a class="reference internal" href="#slice-indices">Slice Indices</a></li>
<li><a class="reference internal" href="#the-proposed-solution">The Proposed Solution</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#open-issues">Open issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated rejected admonition warning">
<p class="admonition-title">Warning</p>
<p>This PEP has been rejected.</p>
<p class="close-button">×</p>
<p>After careful consideration, and a period of meditation, this
proposal has been rejected. The open issues, as well as some
confusion between ranges and slice syntax, raised enough questions
for Guido not to accept it for Python 2.0, and later to reject the
proposal altogether. The new syntax and its intentions were deemed
not obvious enough.</p>
<p>[ TBD: Guido, amend/confirm this, please. Preferably both; this
is a PEP, it should contain <em>all</em> the reasons for rejection
and/or reconsideration, for future reference. ]</p>
<p></p>
</div>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes the “range literal” proposal for Python 2.0.
This PEP tracks the status and ownership of this feature, slated
for introduction in Python 2.0. It contains a description of the
feature and outlines changes necessary to support the feature.
This PEP summarizes discussions held in mailing list forums, and
provides URLs for further information, where appropriate. The CVS
revision history of this file contains the definitive historical
record.</p>
</section>
<section id="list-ranges">
<h2><a class="toc-backref" href="#list-ranges" role="doc-backlink">List ranges</a></h2>
<p>Ranges are sequences of numbers of a fixed stepping, often used in
for-loops. The Python for-loop is designed to iterate over a
sequence directly:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">l</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;a&#39;</span><span class="p">,</span> <span class="s1">&#39;b&#39;</span><span class="p">,</span> <span class="s1">&#39;c&#39;</span><span class="p">,</span> <span class="s1">&#39;d&#39;</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">l</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span> <span class="n">item</span>
<span class="go">a</span>
<span class="go">b</span>
<span class="go">c</span>
<span class="go">d</span>
</pre></div>
</div>
<p>However, this solution is not always prudent. Firstly, problems
arise when altering the sequence in the body of the for-loop,
resulting in the for-loop skipping items. Secondly, it is not
possible to iterate over, say, every second element of the
sequence. And thirdly, it is sometimes necessary to process an
element based on its index, which is not readily available in the
above construct.</p>
<p>For these instances, and others where a range of numbers is
desired, Python provides the <code class="docutils literal notranslate"><span class="pre">range</span></code> builtin function, which
creates a list of numbers. The <code class="docutils literal notranslate"><span class="pre">range</span></code> function takes three
arguments, <em>start</em>, <em>end</em> and <em>step</em>. <em>start</em> and <em>step</em> are
optional, and default to 0 and 1, respectively.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">range</span></code> function creates a list of numbers, starting at
<em>start</em>, with a step of <em>step</em>, up to, but not including <em>end</em>, so
that <code class="docutils literal notranslate"><span class="pre">range(10)</span></code> produces a list that has exactly 10 items, the
numbers 0 through 9.</p>
<p>Using the <code class="docutils literal notranslate"><span class="pre">range</span></code> function, the above example would look like
this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">l</span><span class="p">)):</span>
<span class="gp">... </span> <span class="nb">print</span> <span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="go">a</span>
<span class="go">b</span>
<span class="go">c</span>
<span class="go">d</span>
</pre></div>
</div>
<p>Or, to start at the second element of <code class="docutils literal notranslate"><span class="pre">l</span></code> and processing only
every second element from then on:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">l</span><span class="p">),</span> <span class="mi">2</span><span class="p">):</span>
<span class="gp">... </span> <span class="nb">print</span> <span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="go">b</span>
<span class="go">d</span>
</pre></div>
</div>
<p>There are several disadvantages with this approach:</p>
<ul class="simple">
<li>Clarity of purpose: Adding another function call, possibly with
extra arithmetic to determine the desired length and step of the
list, does not improve readability of the code. Also, it is
possible to “shadow” the builtin <code class="docutils literal notranslate"><span class="pre">range</span></code> function by supplying a
local or global variable with the same name, effectively
replacing it. This may or may not be a desired effect.</li>
<li>Efficiency: because the <code class="docutils literal notranslate"><span class="pre">range</span></code> function can be overridden, the
Python compiler cannot make assumptions about the for-loop, and
has to maintain a separate loop counter.</li>
<li>Consistency: There already is a syntax that is used to denote
ranges, as shown below. This syntax uses the exact same
arguments, though all optional, in the exact same way. It seems
logical to extend this syntax to ranges, to form “range
literals”.</li>
</ul>
</section>
<section id="slice-indices">
<h2><a class="toc-backref" href="#slice-indices" role="doc-backlink">Slice Indices</a></h2>
<p>In Python, a sequence can be indexed in one of two ways:
retrieving a single item, or retrieving a range of items.
Retrieving a range of items results in a new object of the same
type as the original sequence, containing zero or more items from
the original sequence. This is done using a “range notation”:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">l</span><span class="p">[</span><span class="mi">2</span><span class="p">:</span><span class="mi">4</span><span class="p">]</span>
<span class="go">[&#39;c&#39;, &#39;d&#39;]</span>
</pre></div>
</div>
<p>This range notation consists of zero, one or two indices separated
by a colon. The first index is the <em>start</em> index, the second the
<em>end</em>. When either is left out, they default to respectively the
start and the end of the sequence.</p>
<p>There is also an extended range notation, which incorporates
<em>step</em> as well. Though this notation is not currently supported
by most builtin types, if it were, it would work as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">l</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">4</span><span class="p">:</span><span class="mi">2</span><span class="p">]</span>
<span class="go">[&#39;b&#39;, &#39;d&#39;]</span>
</pre></div>
</div>
<p>The third “argument” to the slice syntax is exactly the same as
the <em>step</em> argument to <code class="docutils literal notranslate"><span class="pre">range()</span></code>. The underlying mechanisms of the
standard, and these extended slices, are sufficiently different
and inconsistent that many classes and extensions outside of
mathematical packages do not implement support for the extended
variant. While this should be resolved, it is beyond the scope of
this PEP.</p>
<p>Extended slices do show, however, that there is already a
perfectly valid and applicable syntax to denote ranges in a way
that solve all of the earlier stated disadvantages of the use of
the <code class="docutils literal notranslate"><span class="pre">range()</span></code> function:</p>
<ul class="simple">
<li>It is clearer, more concise syntax, which has already proven to
be both intuitive and easy to learn.</li>
<li>It is consistent with the other use of ranges in Python
(e.g. slices).</li>
<li>Because it is built-in syntax, instead of a builtin function, it
cannot be overridden. This means both that a viewer can be
certain about what the code does, and that an optimizer will not
have to worry about <code class="docutils literal notranslate"><span class="pre">range()</span></code> being “shadowed”.</li>
</ul>
</section>
<section id="the-proposed-solution">
<h2><a class="toc-backref" href="#the-proposed-solution" role="doc-backlink">The Proposed Solution</a></h2>
<p>The proposed implementation of range-literals combines the syntax
for list literals with the syntax for (extended) slices, to form
range literals:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">10</span><span class="p">]</span>
<span class="go">[1, 2, 3, 4, 5, 6, 7, 8, 9]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="p">[:</span><span class="mi">5</span><span class="p">]</span>
<span class="go">[0, 1, 2, 3, 4]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="mi">5</span><span class="p">:</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="go">[5, 4, 3, 2]</span>
</pre></div>
</div>
<p>There is one minor difference between range literals and the slice
syntax: though it is possible to omit all of <em>start</em>, <em>end</em> and
<em>step</em> in slices, it does not make sense to omit <em>end</em> in range
literals. In slices, <em>end</em> would default to the end of the list,
but this has no meaning in range literals.</p>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>The proposed implementation can be found on SourceForge <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>. It
adds a new bytecode, <code class="docutils literal notranslate"><span class="pre">BUILD_RANGE</span></code>, that takes three arguments from
the stack and builds a list on the bases of those. The list is
pushed back on the stack.</p>
<p>The use of a new bytecode is necessary to be able to build ranges
based on other calculations, whose outcome is not known at compile
time.</p>
<p>The code introduces two new functions to <code class="docutils literal notranslate"><span class="pre">listobject.c</span></code>, which are
currently hovering between private functions and full-fledged API
calls.</p>
<p><code class="docutils literal notranslate"><span class="pre">PyList_FromRange()</span></code> builds a list from start, end and step,
returning NULL if an error occurs. Its prototype is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span> <span class="o">*</span> <span class="n">PyList_FromRange</span><span class="p">(</span><span class="n">long</span> <span class="n">start</span><span class="p">,</span> <span class="n">long</span> <span class="n">end</span><span class="p">,</span> <span class="n">long</span> <span class="n">step</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">PyList_GetLenOfRange()</span></code> is a helper function used to determine the
length of a range. Previously, it was a static function in
<code class="docutils literal notranslate"><span class="pre">bltinmodule.c</span></code>, but is now necessary in both <code class="docutils literal notranslate"><span class="pre">listobject.c</span></code> and
<code class="docutils literal notranslate"><span class="pre">bltinmodule.c</span></code> (for <code class="docutils literal notranslate"><span class="pre">xrange</span></code>). It is made non-static solely to avoid
code duplication. Its prototype is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">long</span> <span class="n">PyList_GetLenOfRange</span><span class="p">(</span><span class="n">long</span> <span class="n">start</span><span class="p">,</span> <span class="n">long</span> <span class="n">end</span><span class="p">,</span> <span class="n">long</span> <span class="n">step</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open issues</a></h2>
<ul>
<li>One possible solution to the discrepancy of requiring the <em>end</em>
argument in range literals is to allow the range syntax to
create a “generator”, rather than a list, such as the <code class="docutils literal notranslate"><span class="pre">xrange</span></code>
builtin function does. However, a generator would not be a
list, and it would be impossible, for instance, to assign to
items in the generator, or append to it.<p>The range syntax could conceivably be extended to include tuples
(i.e. immutable lists), which could then be safely implemented
as generators. This may be a desirable solution, especially for
large number arrays: generators require very little in the way
of storage and initialization, and there is only a small
performance impact in calculating and creating the appropriate
number on request. (TBD: is there any at all? Cursory testing
suggests equal performance even in the case of ranges of length
1)</p>
<p>However, even if idea was adopted, would it be wise to “special
case” the second argument, making it optional in one instance of
the syntax, and non-optional in other cases ?</p>
</li>
<li>Should it be possible to mix range syntax with normal list
literals, creating a single list? E.g.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">:</span><span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">]</span>
</pre></div>
</div>
<p>to create:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">]</span>
</pre></div>
</div>
</li>
<li>How should range literals interact with another proposed new
feature, <a class="pep reference internal" href="../pep-0202/" title="PEP 202 List Comprehensions">“list comprehensions”</a>? Specifically, should it be
possible to create lists in list comprehensions? E.g.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="n">x</span><span class="p">:</span><span class="n">y</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="n">y</span> <span class="ow">in</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)]</span>
</pre></div>
</div>
<p>Should this example return a single list with multiple ranges:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
</pre></div>
</div>
<p>Or a list of lists, like so:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]]</span>
</pre></div>
</div>
<p>However, as the syntax and semantics of list comprehensions are
still subject of hot debate, these issues are probably best
addressed by the “list comprehensions” PEP.</p>
</li>
<li>Range literals accept objects other than integers: it performs
<code class="docutils literal notranslate"><span class="pre">PyInt_AsLong()</span></code> on the objects passed in, so as long as the
objects can be coerced into integers, they will be accepted.
The resulting list, however, is always composed of standard
integers.<p>Should range literals create a list of the passed-in type? It
might be desirable in the cases of other builtin types, such as
longs and strings:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="p">[</span> <span class="mi">1</span><span class="n">L</span> <span class="p">:</span> <span class="mi">2</span><span class="n">L</span><span class="o">&lt;&lt;</span><span class="mi">64</span> <span class="p">:</span> <span class="mi">2</span><span class="o">&lt;&lt;</span><span class="mi">32</span><span class="n">L</span> <span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="s2">&quot;a&quot;</span><span class="p">:</span><span class="s2">&quot;z&quot;</span><span class="p">:</span><span class="s2">&quot;b&quot;</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="s2">&quot;a&quot;</span><span class="p">:</span><span class="s2">&quot;z&quot;</span><span class="p">:</span><span class="mi">2</span><span class="p">]</span>
</pre></div>
</div>
<p>However, this might be too much “magic” to be obvious. It might
also present problems with user-defined classes: even if the
base class can be found and a new instance created, the instance
may require additional arguments to <code class="docutils literal notranslate"><span class="pre">__init__</span></code>, causing the
creation to fail.</p>
</li>
<li>The <code class="docutils literal notranslate"><span class="pre">PyList_FromRange()</span></code> and <code class="docutils literal notranslate"><span class="pre">PyList_GetLenOfRange()</span></code> functions need
to be classified: are they part of the API, or should they be
made private functions?</li>
</ul>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the Public Domain.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=100902&amp;group_id=5470">http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=100902&amp;group_id=5470</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0204.rst">https://github.com/python/peps/blob/main/peps/pep-0204.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0204.rst">2024-04-14 20:08:31 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#list-ranges">List ranges</a></li>
<li><a class="reference internal" href="#slice-indices">Slice Indices</a></li>
<li><a class="reference internal" href="#the-proposed-solution">The Proposed Solution</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#open-issues">Open issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0204.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

553
pep-0205/index.html Normal file
View File

@ -0,0 +1,553 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 205 Weak References | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0205/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 205 Weak References | peps.python.org'>
<meta property="og:description" content="Python Enhancement Proposals (PEPs)">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0205/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python Enhancement Proposals (PEPs)">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 205</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 205 Weak References</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Fred L. Drake, Jr. &lt;fred&#32;&#97;t&#32;fdrake.net&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">14-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">11-Jan-2001</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#motivation">Motivation</a><ul>
<li><a class="reference internal" href="#caches-weak-dictionaries">Caches (weak dictionaries)</a></li>
<li><a class="reference internal" href="#circular-references">Circular references</a></li>
</ul>
</li>
<li><a class="reference internal" href="#aspects-of-the-solution-space">Aspects of the Solution Space</a><ul>
<li><a class="reference internal" href="#invalidation">Invalidation</a></li>
<li><a class="reference internal" href="#presentation">Presentation</a></li>
</ul>
</li>
<li><a class="reference internal" href="#proposed-solution">Proposed Solution</a></li>
<li><a class="reference internal" href="#implementation-strategy">Implementation Strategy</a></li>
<li><a class="reference internal" href="#possible-applications">Possible Applications</a></li>
<li><a class="reference internal" href="#previous-weak-reference-work-in-python">Previous Weak Reference Work in Python</a></li>
<li><a class="reference internal" href="#weak-references-in-java">Weak References in Java</a></li>
<li><a class="reference internal" href="#appendix-dianne-hackborn-s-vref-proposal-1995">Appendix Dianne Hackborns vref proposal (1995)</a><ul>
<li><a class="reference internal" href="#proposal-virtual-references">Proposal: Virtual References</a></li>
<li><a class="reference internal" href="#pointer-semantics">Pointer semantics</a></li>
<li><a class="reference internal" href="#proxy-semantics">Proxy semantics</a></li>
</ul>
</li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>There are two basic applications for weak references which have
been noted by Python programmers: object caches and reduction of
pain from circular references.</p>
<section id="caches-weak-dictionaries">
<h3><a class="toc-backref" href="#caches-weak-dictionaries" role="doc-backlink">Caches (weak dictionaries)</a></h3>
<p>There is a need to allow objects to be maintained that represent
external state, mapping a single instance to the external
reality, where allowing multiple instances to be mapped to the
same external resource would create unnecessary difficulty
maintaining synchronization among instances. In these cases,
a common idiom is to support a cache of instances; a factory
function is used to return either a new or existing instance.</p>
<p>The difficulty in this approach is that one of two things must
be tolerated: either the cache grows without bound, or there
needs to be explicit management of the cache elsewhere in the
application. The later can be very tedious and leads to more
code than is really necessary to solve the problem at hand,
and the former can be unacceptable for long-running processes
or even relatively short processes with substantial memory
requirements.</p>
<ul class="simple">
<li>External objects that need to be represented by a single
instance, no matter how many internal users there are. This
can be useful for representing files that need to be written
back to disk in whole rather than locked &amp; modified for
every use.</li>
<li>Objects that are expensive to create, but may be needed by
multiple internal consumers. Similar to the first case, but
not necessarily bound to external resources, and possibly
not an issue for shared state. Weak references are only
useful in this case if there is some flavor of “soft”
references or if there is a high likelihood that users of
individual objects will overlap in lifespan.</li>
</ul>
</section>
<section id="circular-references">
<h3><a class="toc-backref" href="#circular-references" role="doc-backlink">Circular references</a></h3>
<ul class="simple">
<li>DOMs require a huge amount of circular (to parent &amp; document
nodes) references, but these could be eliminated using a weak
dictionary mapping from each node to its parent. This
might be especially useful in the context of something like
<code class="docutils literal notranslate"><span class="pre">xml.dom.pulldom</span></code>, allowing the <code class="docutils literal notranslate"><span class="pre">.unlink()</span></code> operation to become
a no-op.</li>
</ul>
<p>This proposal is divided into the following sections:</p>
<ul class="simple">
<li>Proposed Solution</li>
<li>Implementation Strategy</li>
<li>Possible Applications</li>
<li>Previous Weak Reference Work in Python</li>
<li>Weak References in Java</li>
</ul>
<p>The full text of one early proposal is included as an appendix
since it does not appear to be available on the net.</p>
</section>
</section>
<section id="aspects-of-the-solution-space">
<h2><a class="toc-backref" href="#aspects-of-the-solution-space" role="doc-backlink">Aspects of the Solution Space</a></h2>
<p>There are two distinct aspects to the weak references problem:</p>
<ul class="simple">
<li>Invalidation of weak references</li>
<li>Presentation of weak references to Python code</li>
</ul>
<section id="invalidation">
<h3><a class="toc-backref" href="#invalidation" role="doc-backlink">Invalidation</a></h3>
<p>Past approaches to weak reference invalidation have often hinged
on storing a strong reference and being able to examine all the
instances of weak reference objects, and invalidating them when
the reference count of their referent goes to one (indicating that
the reference stored by the weak reference is the last remaining
reference). This has the advantage that the memory management
machinery in Python need not change, and that any type can be
weakly referenced.</p>
<p>The disadvantage of this approach to invalidation is that it
assumes that the management of the weak references is called
sufficiently frequently that weakly-referenced objects are noticed
within a reasonably short time frame; since this means a scan over
some data structure to invalidate references, an operation which
is O(N) on the number of weakly referenced objects, this is not
effectively amortized for any single object which is weakly
referenced. This also assumes that the application is calling
into code which handles weakly-referenced objects with some
frequency, which makes weak-references less attractive for library
code.</p>
<p>An alternate approach to invalidation is that the de-allocation
code to be aware of the possibility of weak references and make a
specific call into the weak-reference management code to all
invalidation whenever an object is deallocated. This requires a
change in the tp_dealloc handler for weakly-referencable objects;
an additional call is needed at the “top” of the handler for
objects which support weak-referencing, and an efficient way to
map from an object to a chain of weak references for that object
is needed as well.</p>
</section>
<section id="presentation">
<h3><a class="toc-backref" href="#presentation" role="doc-backlink">Presentation</a></h3>
<p>Two ways that weak references are presented to the Python layer
have been as explicit reference objects upon which some operation
is required in order to retrieve a usable reference to the
underlying object, and proxy objects which masquerade as the
original objects as much as possible.</p>
<p>Reference objects are easy to work with when some additional layer
of object management is being added in Python; references can be
checked for liveness explicitly, without having to invoke
operations on the referents and catching some special exception
raised when an invalid weak reference is used.</p>
<p>However, a number of users favor the proxy approach simply because
the weak reference looks so much like the original object.</p>
</section>
</section>
<section id="proposed-solution">
<h2><a class="toc-backref" href="#proposed-solution" role="doc-backlink">Proposed Solution</a></h2>
<p>Weak references should be able to point to any Python object that
may have substantial memory size (directly or indirectly), or hold
references to external resources (database connections, open
files, etc.).</p>
<p>A new module, weakref, will contain new functions used to create
weak references. <code class="docutils literal notranslate"><span class="pre">weakref.ref()</span></code> will create a “weak reference
object” and optionally attach a callback which will be called when
the object is about to be finalized. <code class="docutils literal notranslate"><span class="pre">weakref.mapping()</span></code> will
create a “weak dictionary”. A third function, <code class="docutils literal notranslate"><span class="pre">weakref.proxy()</span></code>,
will create a proxy object that behaves somewhat like the original
object.</p>
<p>A weak reference object will allow access to the referenced object
if it hasnt been collected and to determine if the object still
exists in memory. Retrieving the referent is done by calling the
reference object. If the referent is no longer alive, this will
return None instead.</p>
<p>A weak dictionary maps arbitrary keys to values, but does not own
a reference to the values. When the values are finalized, the
(key, value) pairs for which it is a value are removed from all
the mappings containing such pairs. Like dictionaries, weak
dictionaries are not hashable.</p>
<p>Proxy objects are weak references that attempt to behave like the
object they proxy, as much as they can. Regardless of the
underlying type, proxies are not hashable since their ability to
act as a weak reference relies on a fundamental mutability that
will cause failures when used as dictionary keys even if the
proper hash value is computed before the referent dies, the
resulting proxy cannot be used as a dictionary key since it cannot
be compared once the referent has expired, and comparability is
necessary for dictionary keys. Operations on proxy objects after
the referent dies cause weakref.ReferenceError to be raised in
most cases. “is” comparisons, <code class="docutils literal notranslate"><span class="pre">type()</span></code>, and <code class="docutils literal notranslate"><span class="pre">id()</span></code> will continue to
work, but always refer to the proxy and not the referent.</p>
<p>The callbacks registered with weak references must accept a single
parameter, which will be the weak reference or proxy object
itself. The object cannot be accessed or resurrected in the
callback.</p>
</section>
<section id="implementation-strategy">
<h2><a class="toc-backref" href="#implementation-strategy" role="doc-backlink">Implementation Strategy</a></h2>
<p>The implementation of weak references will include a list of
reference containers that must be cleared for each weakly-referencable
object. If the reference is from a weak dictionary,
the dictionary entry is cleared first. Then, any associated
callback is called with the object passed as a parameter. Once
all callbacks have been called, the object is finalized and
deallocated.</p>
<p>Many built-in types will participate in the weak-reference
management, and any extension type can elect to do so. The type
structure will contain an additional field which provides an
offset into the instance structure which contains a list of weak
reference structures. If the value of the field is &lt;= 0, the
object does not participate. In this case, <code class="docutils literal notranslate"><span class="pre">weakref.ref()</span></code>,
<code class="docutils literal notranslate"><span class="pre">&lt;weakdict&gt;.__setitem__()</span></code> and <code class="docutils literal notranslate"><span class="pre">.setdefault()</span></code>, and item assignment will
raise <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>. If the value of the field is &gt; 0, a new weak
reference can be generated and added to the list.</p>
<p>This approach is taken to allow arbitrary extension types to
participate, without taking a memory hit for numbers or other
small types.</p>
<p>Standard types which support weak references include instances,
functions, and bound &amp; unbound methods. With the addition of
class types (“new-style classes”) in Python 2.2, types grew
support for weak references. Instances of class types are weakly
referencable if they have a base type which is weakly referencable,
the class not specify <code class="docutils literal notranslate"><span class="pre">__slots__</span></code>, or a slot is named <code class="docutils literal notranslate"><span class="pre">__weakref__</span></code>.
Generators also support weak references.</p>
</section>
<section id="possible-applications">
<h2><a class="toc-backref" href="#possible-applications" role="doc-backlink">Possible Applications</a></h2>
<p>PyGTK+ bindings?</p>
<p>Tkinter could avoid circular references by using weak
references from widgets to their parents. Objects wont be
discarded any sooner in the typical case, but there wont be so
much dependence on the programmer calling <code class="docutils literal notranslate"><span class="pre">.destroy()</span></code> before
releasing a reference. This would mostly benefit long-running
applications.</p>
<p>DOM trees.</p>
</section>
<section id="previous-weak-reference-work-in-python">
<h2><a class="toc-backref" href="#previous-weak-reference-work-in-python" role="doc-backlink">Previous Weak Reference Work in Python</a></h2>
<p>Dianne Hackborn has proposed something called “virtual references”.
vref objects are very similar to java.lang.ref.WeakReference
objects, except there is no equivalent to the invalidation
queues. Implementing a “weak dictionary” would be just as
difficult as using only weak references (without the invalidation
queue) in Java. Information on this has disappeared from the Web,
but is included below as an Appendix.</p>
<p>Marc-André Lemburgs mx.Proxy package:</p>
<blockquote>
<div><a class="reference external" href="http://www.lemburg.com/files/python/mxProxy.html">http://www.lemburg.com/files/python/mxProxy.html</a></div></blockquote>
<p>The weakdict module by Dieter Maurer is implemented in C and
Python. It appears that the Web pages have not been updated since
Python 1.5.2a, so Im not yet sure if the implementation is
compatible with Python 2.0.</p>
<blockquote>
<div><a class="reference external" href="http://www.handshake.de/~dieter/weakdict.html">http://www.handshake.de/~dieter/weakdict.html</a></div></blockquote>
<p>PyWeakReference by Alex Shindich:</p>
<blockquote>
<div><a class="reference external" href="http://sourceforge.net/projects/pyweakreference/">http://sourceforge.net/projects/pyweakreference/</a></div></blockquote>
<p>Eric Tiedemann has a weak dictionary implementation:</p>
<blockquote>
<div><a class="reference external" href="http://www.hyperreal.org/~est/python/weak/">http://www.hyperreal.org/~est/python/weak/</a></div></blockquote>
</section>
<section id="weak-references-in-java">
<h2><a class="toc-backref" href="#weak-references-in-java" role="doc-backlink">Weak References in Java</a></h2>
<p><a class="reference external" href="http://java.sun.com/j2se/1.3/docs/api/java/lang/ref/package-summary.html">http://java.sun.com/j2se/1.3/docs/api/java/lang/ref/package-summary.html</a></p>
<p>Java provides three forms of weak references, and one interesting
helper class. The three forms are called “weak”, “soft”, and
“phantom” references. The relevant classes are defined in the
java.lang.ref package.</p>
<p>For each of the reference types, there is an option to add the
reference to a queue when it is invalidated by the memory
allocator. The primary purpose of this facility seems to be that
it allows larger structures to be composed to incorporate
weak-reference semantics without having to impose substantial
additional locking requirements. For instance, it would not be
difficult to use this facility to create a “weak” hash table which
removes keys and referents when a reference is no longer used
elsewhere. Using weak references for the objects without some
sort of notification queue for invalidations leads to much more
tedious implementation of the various operations required on hash
tables. This can be a performance bottleneck if deallocations of
the stored objects are infrequent.</p>
<p>Javas “weak” references are most like Dianne Hackborns old vref
proposal: a reference object refers to a single Python object,
but does not own a reference to that object. When that object is
deallocated, the reference object is invalidated. Users of the
reference object can easily determine that the reference has been
invalidated, or a NullObjectDereferenceError can be raised when
an attempt is made to use the referred-to object.</p>
<p>The “soft” references are similar, but are not invalidated as soon
as all other references to the referred-to object have been
released. The “soft” reference does own a reference, but allows
the memory allocator to free the referent if the memory is needed
elsewhere. It is not clear whether this means soft references are
released before the <code class="docutils literal notranslate"><span class="pre">malloc()</span></code> implementation calls <code class="docutils literal notranslate"><span class="pre">sbrk()</span></code> or its
equivalent, or if soft references are only cleared when <code class="docutils literal notranslate"><span class="pre">malloc()</span></code>
returns <code class="docutils literal notranslate"><span class="pre">NULL</span></code>.</p>
<p>“Phantom” references are a little different; unlike weak and soft
references, the referent is not cleared when the reference is
added to its queue. When all phantom references for an object
are dequeued, the object is cleared. This can be used to keep an
object alive until some additional cleanup is performed which
needs to happen before the objects <code class="docutils literal notranslate"><span class="pre">.finalize()</span></code> method is called.</p>
<p>Unlike the other two reference types, “phantom” references must be
associated with an invalidation queue.</p>
</section>
<section id="appendix-dianne-hackborn-s-vref-proposal-1995">
<h2><a class="toc-backref" href="#appendix-dianne-hackborn-s-vref-proposal-1995" role="doc-backlink">Appendix Dianne Hackborns vref proposal (1995)</a></h2>
<p>[This has been indented and paragraphs reflowed, but there have be
no content changes. Fred]</p>
<section id="proposal-virtual-references">
<h3><a class="toc-backref" href="#proposal-virtual-references" role="doc-backlink">Proposal: Virtual References</a></h3>
<p>In an attempt to partly address the recurring discussion
concerning reference counting vs. garbage collection, I would like
to propose an extension to Python which should help in the
creation of “well structured” cyclic graphs. In particular, it
should allow at least trees with parent back-pointers and
doubly-linked lists to be created without worry about cycles.</p>
<p>The basic mechanism Id like to propose is that of a “virtual
reference,” or a “vref” from here on out. A vref is essentially a
handle on an object that does not increment the objects reference
count. This means that holding a vref on an object will not keep
the object from being destroyed. This would allow the Python
programmer, for example, to create the aforementioned tree
structure, which is automatically destroyed when it
is no longer in use by making all of the parent back-references
into vrefs, they no longer create reference cycles which keep the
tree from being destroyed.</p>
<p>In order to implement this mechanism, the Python core must ensure
that no -real- pointers are ever left referencing objects that no
longer exist. The implementation I would like to propose involves
two basic additions to the current Python system:</p>
<ol class="arabic simple">
<li>A new “vref” type, through which the Python programmer creates
and manipulates virtual references. Internally, it is
basically a C-level Python object with a pointer to the Python
object it is a reference to. Unlike all other Python code,
however, it does not change the reference count of this object.
In addition, it includes two pointers to implement a
doubly-linked list, which is used below.</li>
<li>The addition of a new field to the basic Python object
[<code class="docutils literal notranslate"><span class="pre">PyObject_Head</span></code> in object.h], which is either <code class="docutils literal notranslate"><span class="pre">NULL</span></code>, or points to
the head of a list of all vref objects that reference it. When
a vref object attaches itself to another object, it adds itself
to this linked list. Then, if an object with any vrefs on it
is deallocated, it may walk this list and ensure that all of
the vrefs on it point to some safe value, e.g. Nothing.</li>
</ol>
<p>This implementation should hopefully have a minimal impact on the
current Python core when no vrefs exist, it should only add one
pointer to all objects, and a check for a <code class="docutils literal notranslate"><span class="pre">NULL</span></code> pointer every time
an object is deallocated.</p>
<p>Back at the Python language level, I have considered two possible
semantics for the vref object </p>
</section>
<section id="pointer-semantics">
<h3><a class="toc-backref" href="#pointer-semantics" role="doc-backlink">Pointer semantics</a></h3>
<p>In this model, a vref behaves essentially like a Python-level
pointer; the Python program must explicitly dereference the vref
to manipulate the actual object it references.</p>
<p>An example vref module using this model could include the
function “new”; When used as MyVref = vref.new(MyObject), it
returns a new vref object such that <code class="docutils literal notranslate"><span class="pre">MyVref.object</span> <span class="pre">==</span> <span class="pre">MyObject</span></code>.
<code class="docutils literal notranslate"><span class="pre">MyVref.object</span></code> would then change to Nothing if
<code class="docutils literal notranslate"><span class="pre">MyObject</span></code> is ever deallocated.</p>
<p>For a concrete example, we may introduce some new C-style syntax:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">&amp;</span></code> unary operator, creates a vref on an object, same as <code class="docutils literal notranslate"><span class="pre">vref.new()</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">*</span></code> unary operator, dereference a vref, same as <code class="docutils literal notranslate"><span class="pre">VrefObject.object</span></code>.</li>
</ul>
<p>We can then define:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">1.</span> <span class="nb">type</span><span class="p">(</span><span class="o">&amp;</span><span class="n">MyObject</span><span class="p">)</span> <span class="o">==</span> <span class="n">vref</span><span class="o">.</span><span class="n">VrefType</span>
<span class="mf">2.</span> <span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">MyObject</span><span class="p">)</span> <span class="o">==</span> <span class="n">MyObject</span>
<span class="mf">3.</span> <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="o">&amp;</span><span class="n">MyObject</span><span class="p">))</span><span class="o">.</span><span class="n">attr</span> <span class="o">==</span> <span class="n">MyObject</span><span class="o">.</span><span class="n">attr</span>
<span class="mf">4.</span> <span class="o">&amp;&amp;</span><span class="n">MyObject</span> <span class="o">==</span> <span class="n">Nothing</span>
<span class="mf">5.</span> <span class="o">*</span><span class="n">MyObject</span> <span class="o">-&gt;</span> <span class="n">exception</span>
</pre></div>
</div>
<p>Rule #4 is subtle, but comes about because we have made a vref
to (a vref with no real references). Thus the outer vref is
cleared to Nothing when the inner one inevitably disappears.</p>
</section>
<section id="proxy-semantics">
<h3><a class="toc-backref" href="#proxy-semantics" role="doc-backlink">Proxy semantics</a></h3>
<p>In this model, the Python programmer manipulates vref objects
just as if she were manipulating the object it is a reference
of. This is accomplished by implementing the vref so that all
operations on it are redirected to its referenced object. With
this model, the dereference operator (*) no longer makes sense;
instead, we have only the reference operator (&amp;), and define:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">1.</span> <span class="nb">type</span><span class="p">(</span><span class="o">&amp;</span><span class="n">MyObject</span><span class="p">)</span> <span class="o">==</span> <span class="nb">type</span><span class="p">(</span><span class="n">MyObject</span><span class="p">)</span>
<span class="mf">2.</span> <span class="o">&amp;</span><span class="n">MyObject</span> <span class="o">==</span> <span class="n">MyObject</span>
<span class="mf">3.</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">MyObject</span><span class="p">)</span><span class="o">.</span><span class="n">attr</span> <span class="o">==</span> <span class="n">MyObject</span><span class="o">.</span><span class="n">attr</span>
<span class="mf">4.</span> <span class="o">&amp;&amp;</span><span class="n">MyObject</span> <span class="o">==</span> <span class="n">MyObject</span>
</pre></div>
</div>
<p>Again, rule #4 is important here, the outer vref is in fact a
reference to the original object, and -not- the inner vref.
This is because all operations applied to a vref actually apply
to its object, so that creating a vref of a vref actually
results in creating a vref of the latters object.</p>
<p>The first, pointer semantics, has the advantage that it would be
very easy to implement; the vref type is extremely simple,
requiring at minimum a single attribute, object, and a function to
create a reference.</p>
<p>However, I really like the proxy semantics. Not only does it put
less of a burden on the Python programmer, but it allows you to do
nice things like use a vref anywhere you would use the actual
object. Unfortunately, it would probably an extreme pain, if not
practically impossible, to implement in the current Python
implementation. I do have some thoughts, though, on how to do
this, if it seems interesting; one possibility is to introduce new
type-checking functions which handle the vref. This would
hopefully older C modules which dont expect vrefs to simply
return a type error, until they can be fixed.</p>
<p>Finally, there are some other additional capabilities that this
system could provide. One that seems particularly interesting to
me involves allowing the Python programmer to add “destructor”
function to a vref this Python function would be called
immediately prior to the referenced object being deallocated,
allowing a Python program to invisibly attach itself to another
object and watch for it to disappear. This seems neat, though I
havent actually come up with any practical uses for it, yet… :)</p>
<p> Dianne</p>
</section>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0205.rst">https://github.com/python/peps/blob/main/peps/pep-0205.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0205.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#motivation">Motivation</a><ul>
<li><a class="reference internal" href="#caches-weak-dictionaries">Caches (weak dictionaries)</a></li>
<li><a class="reference internal" href="#circular-references">Circular references</a></li>
</ul>
</li>
<li><a class="reference internal" href="#aspects-of-the-solution-space">Aspects of the Solution Space</a><ul>
<li><a class="reference internal" href="#invalidation">Invalidation</a></li>
<li><a class="reference internal" href="#presentation">Presentation</a></li>
</ul>
</li>
<li><a class="reference internal" href="#proposed-solution">Proposed Solution</a></li>
<li><a class="reference internal" href="#implementation-strategy">Implementation Strategy</a></li>
<li><a class="reference internal" href="#possible-applications">Possible Applications</a></li>
<li><a class="reference internal" href="#previous-weak-reference-work-in-python">Previous Weak Reference Work in Python</a></li>
<li><a class="reference internal" href="#weak-references-in-java">Weak References in Java</a></li>
<li><a class="reference internal" href="#appendix-dianne-hackborn-s-vref-proposal-1995">Appendix Dianne Hackborns vref proposal (1995)</a><ul>
<li><a class="reference internal" href="#proposal-virtual-references">Proposal: Virtual References</a></li>
<li><a class="reference internal" href="#pointer-semantics">Pointer semantics</a></li>
<li><a class="reference internal" href="#proxy-semantics">Proxy semantics</a></li>
</ul>
</li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0205.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

223
pep-0206/index.html Normal file
View File

@ -0,0 +1,223 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 206 Python Advanced Library | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0206/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 206 Python Advanced Library | peps.python.org'>
<meta property="og:description" content="This PEP describes the Python Advanced Library, a collection of high-quality and frequently-used third party extension modules.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0206/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the Python Advanced Library, a collection of high-quality and frequently-used third party extension modules.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 206</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 206 Python Advanced Library</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">A.M. Kuchling &lt;amk&#32;&#97;t&#32;amk.ca&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">14-Jul-2000</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#batteries-included-philosophy">Batteries Included Philosophy</a></li>
<li><a class="reference internal" href="#domain-web-tasks">Domain: Web tasks</a></li>
<li><a class="reference internal" href="#domain-scientific-programming">Domain: Scientific Programming</a></li>
<li><a class="reference internal" href="#domain-application-development">Domain: Application Development</a></li>
<li><a class="reference internal" href="#domain-education">Domain: Education</a></li>
<li><a class="reference internal" href="#software-covered-by-the-gnu-general-public-license">Software covered by the GNU General Public License</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated withdrawn admonition important">
<p class="admonition-title">Important</p>
<p>This PEP has been withdrawn.</p>
<p class="close-button">×</p>
<p></p>
</div>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes the Python Advanced Library, a collection of
high-quality and frequently-used third party extension modules.</p>
</section>
<section id="batteries-included-philosophy">
<h2><a class="toc-backref" href="#batteries-included-philosophy" role="doc-backlink">Batteries Included Philosophy</a></h2>
<p>The Python source distribution has long maintained the philosophy
of “batteries included” having a rich and versatile standard
library which is immediately available, without making the user
download separate packages. This gives the Python language a head
start in many projects.</p>
<p>However, the standard library modules arent always the best
choices for a job. Some library modules were quick hacks
(e.g. <code class="docutils literal notranslate"><span class="pre">calendar</span></code>, <code class="docutils literal notranslate"><span class="pre">commands</span></code>), some were designed poorly and are now
near-impossible to fix (<code class="docutils literal notranslate"><span class="pre">cgi</span></code>), and some have been rendered obsolete
by other, more complete modules (<code class="docutils literal notranslate"><span class="pre">binascii</span></code> offers the same features
as the <code class="docutils literal notranslate"><span class="pre">binhex</span></code>, <code class="docutils literal notranslate"><span class="pre">uu</span></code>, <code class="docutils literal notranslate"><span class="pre">base64</span></code> modules). This PEP describes a list of
third-party modules that make Python more competitive for various
application domains, forming the Python Advanced Library.</p>
<p>The deliverable is a set of scripts that will retrieve, build, and
install the packages for a particular application domain. The
Python Package Index now contains enough information to let
software automatically find packages and download them, so the
time is ripe to implement this.</p>
<p>Currently this document doesnt suggest <em>removing</em> modules from
the standard library that are superseded by a third-party module.
Thats difficult to do because it entails many backward-compatibility
problems, so its not worth bothering with now.</p>
<p>Please suggest additional domains of interest.</p>
</section>
<section id="domain-web-tasks">
<h2><a class="toc-backref" href="#domain-web-tasks" role="doc-backlink">Domain: Web tasks</a></h2>
<p>XML parsing: ElementTree + SAX.</p>
<p>URL retrieval: libcurl? other possibilities?</p>
<p>HTML parsing: mxTidy? HTMLParser?</p>
<p>Async network I/O: Twisted</p>
<p>RDF parser: ???</p>
<p>HTTP serving: ???</p>
<p>HTTP cookie processing: ???</p>
<p>Web framework: A WSGI gateway, perhaps? Paste?</p>
<p>Graphics: PIL, Chaco.</p>
</section>
<section id="domain-scientific-programming">
<h2><a class="toc-backref" href="#domain-scientific-programming" role="doc-backlink">Domain: Scientific Programming</a></h2>
<p>Numeric: Numeric, SciPy</p>
<p>Graphics: PIL, Chaco.</p>
</section>
<section id="domain-application-development">
<h2><a class="toc-backref" href="#domain-application-development" role="doc-backlink">Domain: Application Development</a></h2>
<p>GUI toolkit: ???</p>
<p>Graphics: Reportlab for PDF generation.</p>
</section>
<section id="domain-education">
<h2><a class="toc-backref" href="#domain-education" role="doc-backlink">Domain: Education</a></h2>
<p>Graphics: PyGame</p>
</section>
<section id="software-covered-by-the-gnu-general-public-license">
<h2><a class="toc-backref" href="#software-covered-by-the-gnu-general-public-license" role="doc-backlink">Software covered by the GNU General Public License</a></h2>
<p>Some of these third-party modules are covered by the GNU General
Public License and the GNU Lesser General Public License.
Providing a script to download and install such packages, or even
assembling all these packages into a single tarball or CD-ROM,
shouldnt cause any difficulties with the GPL, under the “mere
aggregation” clause of the license.</p>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
<p>What other application domains are important?</p>
<p>Should this just be a set of Ubuntu or Debian packages? Compiling
things such as PyGame can be very complicated and may be too
difficult to automate.</p>
</section>
<section id="acknowledgements">
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
<p>The PEP is based on an earlier draft PEP by Moshe Zadka, titled
“2.0 Batteries Included.”</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0206.rst">https://github.com/python/peps/blob/main/peps/pep-0206.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0206.rst">2024-04-14 13:35:25 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#batteries-included-philosophy">Batteries Included Philosophy</a></li>
<li><a class="reference internal" href="#domain-web-tasks">Domain: Web tasks</a></li>
<li><a class="reference internal" href="#domain-scientific-programming">Domain: Scientific Programming</a></li>
<li><a class="reference internal" href="#domain-application-development">Domain: Application Development</a></li>
<li><a class="reference internal" href="#domain-education">Domain: Education</a></li>
<li><a class="reference internal" href="#software-covered-by-the-gnu-general-public-license">Software covered by the GNU General Public License</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0206.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

587
pep-0207/index.html Normal file
View File

@ -0,0 +1,587 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 207 Rich Comparisons | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0207/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 207 Rich Comparisons | peps.python.org'>
<meta property="og:description" content="This PEP proposes several new features for comparisons:">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0207/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP proposes several new features for comparisons:">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 207</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 207 Rich Comparisons</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;, David Ascher &lt;DavidA&#32;&#97;t&#32;ActiveState.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">25-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#previous-work">Previous Work</a></li>
<li><a class="reference internal" href="#concerns">Concerns</a></li>
<li><a class="reference internal" href="#proposed-resolutions">Proposed Resolutions</a></li>
<li><a class="reference internal" href="#implementation-proposal">Implementation Proposal</a><ul>
<li><a class="reference internal" href="#c-api">C API</a></li>
<li><a class="reference internal" href="#changes-to-the-interpreter">Changes to the interpreter</a></li>
<li><a class="reference internal" href="#classes">Classes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#appendix">Appendix</a></li>
<li><a class="reference internal" href="#id1">Abstract</a></li>
<li><a class="reference internal" href="#id2">Motivation</a></li>
<li><a class="reference internal" href="#current-state-of-affairs">Current State of Affairs</a><ul>
<li><a class="reference internal" href="#proposed-mechanism">Proposed Mechanism</a></li>
<li><a class="reference internal" href="#chained-comparisons">Chained Comparisons</a><ul>
<li><a class="reference internal" href="#problem">Problem</a></li>
<li><a class="reference internal" href="#solution">Solution</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP proposes several new features for comparisons:</p>
<ul class="simple">
<li>Allow separately overloading of &lt;, &gt;, &lt;=, &gt;=, ==, !=, both in
classes and in C extensions.</li>
<li>Allow any of those overloaded operators to return something else
besides a Boolean result.</li>
</ul>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>The main motivation comes from NumPy, whose users agree that A&lt;B
should return an array of elementwise comparison outcomes; they
currently have to spell this as less(A,B) because A&lt;B can only
return a Boolean result or raise an exception.</p>
<p>An additional motivation is that frequently, types dont have a
natural ordering, but still need to be compared for equality.
Currently such a type <strong>must</strong> implement comparison and thus define
an arbitrary ordering, just so that equality can be tested.</p>
<p>Also, for some object types an equality test can be implemented
much more efficiently than an ordering test; for example, lists
and dictionaries that differ in length are unequal, but the
ordering requires inspecting some (potentially all) items.</p>
</section>
<section id="previous-work">
<h2><a class="toc-backref" href="#previous-work" role="doc-backlink">Previous Work</a></h2>
<p>Rich Comparisons have been proposed before; in particular by David
Ascher, after experience with Numerical Python:</p>
<blockquote>
<div><a class="reference external" href="http://starship.python.net/crew/da/proposals/richcmp.html">http://starship.python.net/crew/da/proposals/richcmp.html</a></div></blockquote>
<p>It is also included below as an Appendix. Most of the material in
this PEP is derived from Davids proposal.</p>
</section>
<section id="concerns">
<h2><a class="toc-backref" href="#concerns" role="doc-backlink">Concerns</a></h2>
<ol class="arabic simple">
<li>Backwards compatibility, both at the Python level (classes using
<code class="docutils literal notranslate"><span class="pre">__cmp__</span></code> need not be changed) and at the C level (extensions
defining <code class="docutils literal notranslate"><span class="pre">tp_comparea</span></code> need not be changed, code using
<code class="docutils literal notranslate"><span class="pre">PyObject_Compare()</span></code> must work even if the compared objects use
the new rich comparison scheme).</li>
<li>When A&lt;B returns a matrix of elementwise comparisons, an easy
mistake to make is to use this expression in a Boolean context.
Without special precautions, it would always be true. This use
should raise an exception instead.</li>
<li>If a class overrides x==y but nothing else, should x!=y be
computed as not(x==y), or fail? What about the similar
relationship between &lt; and &gt;=, or between &gt; and &lt;=?</li>
<li>Similarly, should we allow x&lt;y to be calculated from y&gt;x? And
x&lt;=y from not(x&gt;y)? And x==y from y==x, or x!=y from y!=x?</li>
<li>When comparison operators return elementwise comparisons, what
to do about shortcut operators like A&lt;B&lt;C, <code class="docutils literal notranslate"><span class="pre">A&lt;B</span> <span class="pre">and</span> <span class="pre">C&lt;D</span></code>,
<code class="docutils literal notranslate"><span class="pre">A&lt;B</span> <span class="pre">or</span> <span class="pre">C&lt;D</span></code>?</li>
<li>What to do about <code class="docutils literal notranslate"><span class="pre">min()</span></code> and <code class="docutils literal notranslate"><span class="pre">max()</span></code>, the in and not in
operators, <code class="docutils literal notranslate"><span class="pre">list.sort()</span></code>, dictionary key comparison, and other
uses of comparisons by built-in operations?</li>
</ol>
</section>
<section id="proposed-resolutions">
<h2><a class="toc-backref" href="#proposed-resolutions" role="doc-backlink">Proposed Resolutions</a></h2>
<ol class="arabic">
<li>Full backwards compatibility can be achieved as follows. When
an object defines <code class="docutils literal notranslate"><span class="pre">tp_compare()</span></code> but not <code class="docutils literal notranslate"><span class="pre">tp_richcompare()</span></code>, and a
rich comparison is requested, the outcome of <code class="docutils literal notranslate"><span class="pre">tp_compare()</span></code> is
used in the obvious way. E.g. if “&lt;” is requested, an exception if
<code class="docutils literal notranslate"><span class="pre">tp_compare()</span></code> raises an exception, the outcome is 1 if
<code class="docutils literal notranslate"><span class="pre">tp_compare()</span></code> is negative, and 0 if it is zero or positive. Etc.<p>Full forward compatibility can be achieved as follows. When a
classic comparison is requested on an object that implements
<code class="docutils literal notranslate"><span class="pre">tp_richcompare()</span></code>, up to three comparisons are used: first == is
tried, and if it returns true, 0 is returned; next, &lt; is tried
and if it returns true, -1 is returned; next, &gt; is tried and if
it returns true, +1 is returned. If any operator tried returns
a non-Boolean value (see below), the exception raised by
conversion to Boolean is passed through. If none of the
operators tried returns true, the classic comparison fallbacks
are tried next.</p>
<p>(I thought long and hard about the order in which the three
comparisons should be tried. At one point I had a convincing
argument for doing it in this order, based on the behavior of
comparisons for cyclical data structures. But since that code
has changed again, Im not so sure that it makes a difference
any more.)</p>
</li>
<li>Any type that returns a collection of Booleans instead of a
single boolean should define <code class="docutils literal notranslate"><span class="pre">nb_nonzero()</span></code> to raise an exception.
Such a type is considered a non-Boolean.</li>
<li>The == and != operators are not assumed to be each others
complement (e.g. IEEE 754 floating point numbers do not satisfy
this). It is up to the type to implement this if desired.
Similar for &lt; and &gt;=, or &gt; and &lt;=; there are lots of examples
where these assumptions arent true (e.g. tabnanny).</li>
<li>The reflexivity rules <strong>are</strong> assumed by Python. Thus, the
interpreter may swap y&gt;x with x&lt;y, y&gt;=x with x&lt;=y, and may swap
the arguments of x==y and x!=y. (Note: Python currently assumes
that x==x is always true and x!=x is never true; this should not
be assumed.)</li>
<li>In the current proposal, when A&lt;B returns an array of
elementwise comparisons, this outcome is considered non-Boolean,
and its interpretation as Boolean by the shortcut operators
raises an exception. David Aschers proposal tries to deal
with this; I dont think this is worth the additional complexity
in the code generator. Instead of A&lt;B&lt;C, you can write
(A&lt;B)&amp;(B&lt;C).</li>
<li>The <code class="docutils literal notranslate"><span class="pre">min()</span></code> and <code class="docutils literal notranslate"><span class="pre">list.sort()</span></code> operations will only use the
&lt; operator; max() will only use the &gt; operator. The in and
not in operators and dictionary lookup will only use the ==
operator.</li>
</ol>
</section>
<section id="implementation-proposal">
<h2><a class="toc-backref" href="#implementation-proposal" role="doc-backlink">Implementation Proposal</a></h2>
<p>This closely follows David Aschers proposal.</p>
<section id="c-api">
<h3><a class="toc-backref" href="#c-api" role="doc-backlink">C API</a></h3>
<ul>
<li>New functions:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span> <span class="o">*</span><span class="n">PyObject_RichCompare</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span>
</pre></div>
</div>
<p>This performs the requested rich comparison, returning a Python
object or raising an exception. The 3rd argument must be one of
Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT or Py_GE.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">PyObject_RichCompareBool</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span>
</pre></div>
</div>
<p>This performs the requested rich comparison, returning a
Boolean: -1 for exception, 0 for false, 1 for true. The 3rd
argument must be one of Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT or
Py_GE. Note that when <code class="docutils literal notranslate"><span class="pre">PyObject_RichCompare()</span></code> returns a
non-Boolean object, <code class="docutils literal notranslate"><span class="pre">PyObject_RichCompareBool()</span></code> will raise an
exception.</p>
</li>
<li>New typedef:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">PyObject</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="n">richcmpfunc</span><span class="p">)</span> <span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="p">,</span> <span class="nb">int</span><span class="p">);</span>
</pre></div>
</div>
</li>
<li>New slot in type object, replacing spare tp_xxx7:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">richcmpfunc</span> <span class="n">tp_richcompare</span><span class="p">;</span>
</pre></div>
</div>
<p>This should be a function with the same signature as
<code class="docutils literal notranslate"><span class="pre">PyObject_RichCompare()</span></code>, and performing the same comparison.
At least one of the arguments is of the type whose
tp_richcompare slot is being used, but the other may have a
different type. If the function cannot compare the particular
combination of objects, it should return a new reference to
<code class="docutils literal notranslate"><span class="pre">Py_NotImplemented</span></code>.</p>
</li>
<li><code class="docutils literal notranslate"><span class="pre">PyObject_Compare()</span></code> is changed to try rich comparisons if they
are defined (but only if classic comparisons arent defined).</li>
</ul>
</section>
<section id="changes-to-the-interpreter">
<h3><a class="toc-backref" href="#changes-to-the-interpreter" role="doc-backlink">Changes to the interpreter</a></h3>
<ul class="simple">
<li>Whenever <code class="docutils literal notranslate"><span class="pre">PyObject_Compare()</span></code> is called with the intent of getting
the outcome of a particular comparison (e.g. in <code class="docutils literal notranslate"><span class="pre">list.sort()</span></code>, and
of course for the comparison operators in ceval.c), the code is
changed to call <code class="docutils literal notranslate"><span class="pre">PyObject_RichCompare()</span></code> or
<code class="docutils literal notranslate"><span class="pre">PyObject_RichCompareBool()</span></code> instead; if the C code needs to know
the outcome of the comparison, <code class="docutils literal notranslate"><span class="pre">PyObject_IsTrue()</span></code> is called on
the result (which may raise an exception).</li>
<li>Most built-in types that currently define a comparison will be
modified to define a rich comparison instead. (This is
optional; Ive converted lists, tuples, complex numbers, and
arrays so far, and am not sure whether I will convert others.)</li>
</ul>
</section>
<section id="classes">
<h3><a class="toc-backref" href="#classes" role="doc-backlink">Classes</a></h3>
<ul class="simple">
<li>Classes can define new special methods <code class="docutils literal notranslate"><span class="pre">__lt__</span></code>, <code class="docutils literal notranslate"><span class="pre">__le__</span></code>, <code class="docutils literal notranslate"><span class="pre">__eq__</span></code>,
<code class="docutils literal notranslate"><span class="pre">__ne__</span></code>, <code class="docutils literal notranslate"><span class="pre">__gt__</span></code>, <code class="docutils literal notranslate"><span class="pre">__ge__</span></code> to override the corresponding operators.
(I.e., &lt;, &lt;=, ==, !=, &gt;, &gt;=. You gotta love the Fortran
heritage.) If a class defines <code class="docutils literal notranslate"><span class="pre">__cmp__</span></code> as well, it is only used
when <code class="docutils literal notranslate"><span class="pre">__lt__</span></code> etc. have been tried and return <code class="docutils literal notranslate"><span class="pre">NotImplemented</span></code>.</li>
</ul>
</section>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
<section id="appendix">
<h2><a class="toc-backref" href="#appendix" role="doc-backlink">Appendix</a></h2>
<p>Here is most of David Aschers original proposal (version 0.2.1,
dated Wed Jul 22 16:49:28 1998; Ive left the Contents, History
and Patches sections out). It addresses almost all concerns
above.</p>
</section>
<section id="id1">
<h2><a class="toc-backref" href="#id1" role="doc-backlink">Abstract</a></h2>
<p>A new mechanism allowing comparisons of Python objects to return
values other than -1, 0, or 1 (or raise exceptions) is
proposed. This mechanism is entirely backwards compatible, and can
be controlled at the level of the C <code class="docutils literal notranslate"><span class="pre">PyObject</span></code> type or of the Python
class definition. There are three cooperating parts to the
proposed mechanism:</p>
<ul class="simple">
<li>the use of the last slot in the type object structure to store a
pointer to a rich comparison function</li>
<li>the addition of special methods for classes</li>
<li>the addition of an optional argument to the builtin <code class="docutils literal notranslate"><span class="pre">cmp()</span></code>
function.</li>
</ul>
</section>
<section id="id2">
<h2><a class="toc-backref" href="#id2" role="doc-backlink">Motivation</a></h2>
<p>The current comparison protocol for Python objects assumes that
any two Python objects can be compared (as of Python 1.5, object
comparisons can raise exceptions), and that the return value for
any comparison should be -1, 0 or 1. -1 indicates that the first
argument to the comparison function is less than the right one, +1
indicating the contrapositive, and 0 indicating that the two
objects are equal. While this mechanism allows the establishment
of an order relationship (e.g. for use by the <code class="docutils literal notranslate"><span class="pre">sort()</span></code> method of list
objects), it has proven to be limited in the context of Numeric
Python (NumPy).</p>
<p>Specifically, NumPy allows the creation of multidimensional
arrays, which support most of the numeric operators. Thus:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="n">array</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">))</span> <span class="n">y</span> <span class="o">=</span> <span class="n">array</span><span class="p">((</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">4</span><span class="p">))</span>
</pre></div>
</div>
<p>are two NumPy arrays. While they can be added elementwise,:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">z</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span> <span class="c1"># z == array((3,4,7,8))</span>
</pre></div>
</div>
<p>they cannot be compared in the current framework - the released
version of NumPy compares the pointers, (thus yielding junk
information) which was the only solution before the recent
addition of the ability (in 1.5) to raise exceptions in comparison
functions.</p>
<p>Even with the ability to raise exceptions, the current protocol
makes array comparisons useless. To deal with this fact, NumPy
includes several functions which perform the comparisons: <code class="docutils literal notranslate"><span class="pre">less()</span></code>,
<code class="docutils literal notranslate"><span class="pre">less_equal()</span></code>, <code class="docutils literal notranslate"><span class="pre">greater()</span></code>, <code class="docutils literal notranslate"><span class="pre">greater_equal()</span></code>, <code class="docutils literal notranslate"><span class="pre">equal()</span></code>,
<code class="docutils literal notranslate"><span class="pre">not_equal()</span></code>. These functions return arrays with the same shape as
their arguments (modulo broadcasting), filled with 0s and 1s
depending on whether the comparison is true or not for each
element pair. Thus, for example, using the arrays x and y defined
above:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">less</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">)</span>
</pre></div>
</div>
<p>would be an array containing the numbers (1,0,0,0).</p>
<p>The current proposal is to modify the Python object interface to
allow the NumPy package to make it so that x &lt; y returns the same
thing as less(x,y). The exact return value is up to the NumPy
package what this proposal really asks for is changing the
Python core so that extension objects have the ability to return
something other than -1, 0, 1, should their authors choose to do
so.</p>
</section>
<section id="current-state-of-affairs">
<h2><a class="toc-backref" href="#current-state-of-affairs" role="doc-backlink">Current State of Affairs</a></h2>
<p>The current protocol is, at the C level, that each object type
defines a <code class="docutils literal notranslate"><span class="pre">tp_compare</span></code> slot, which is a pointer to a function which
takes two <code class="docutils literal notranslate"><span class="pre">PyObject*</span></code> references and returns -1, 0, or 1. This
function is called by the <code class="docutils literal notranslate"><span class="pre">PyObject_Compare()</span></code> function defined in
the C API. <code class="docutils literal notranslate"><span class="pre">PyObject_Compare()</span></code> is also called by the builtin
function <code class="docutils literal notranslate"><span class="pre">cmp()</span></code> which takes two arguments.</p>
<section id="proposed-mechanism">
<h3><a class="toc-backref" href="#proposed-mechanism" role="doc-backlink">Proposed Mechanism</a></h3>
<ol class="arabic">
<li>Changes to the C structure for type objects<p>The last available slot in the <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span></code>, reserved up to now
for future expansion, is used to optionally store a pointer to a
new comparison function, of type richcmpfunc defined by:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">PyObject</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span><span class="n">richcmpfunc</span><span class="p">)</span>
<span class="n">Py_PROTO</span><span class="p">((</span><span class="n">PyObject</span> <span class="o">*</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="p">,</span> <span class="nb">int</span><span class="p">));</span>
</pre></div>
</div>
<p>This function takes three arguments. The first two are the objects
to be compared, and the third is an integer corresponding to an
opcode (one of LT, LE, EQ, NE, GT, GE). If this slot is left NULL,
then rich comparison for that object type is not supported (except
for class instances whose class provide the special methods
described below).</p>
<p>The above opcodes need to be added to the published Python/C API
(probably under the names Py_LT, Py_LE, etc.)</p>
</li>
<li>Additions of special methods for classes<p>Classes wishing to support the rich comparison mechanisms must add
one or more of the following new special methods:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__lt__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="fm">__le__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="fm">__gt__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="fm">__ge__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="fm">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="fm">__ne__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Each of these is called when the class instance is the on the
left-hand-side of the corresponding operators (&lt;, &lt;=, &gt;, &gt;=, ==,
and != or &lt;&gt;). The argument other is set to the object on the
right side of the operator. The return value of these methods is
up to the class implementor (after all, thats the entire point of
the proposal).</p>
<p>If the object on the left side of the operator does not define an
appropriate rich comparison operator (either at the C level or
with one of the special methods, then the comparison is reversed,
and the right hand operator is called with the opposite operator,
and the two objects are swapped. This assumes that a &lt; b and b &gt; a
are equivalent, as are a &lt;= b and b &gt;= a, and that == and != are
commutative (e.g. a == b if and only if b == a).</p>
<p>For example, if obj1 is an object which supports the rich
comparison protocol and x and y are objects which do not support
the rich comparison protocol, then obj1 &lt; x will call the <code class="docutils literal notranslate"><span class="pre">__lt__</span></code>
method of obj1 with x as the second argument. x &lt; obj1 will call
obj1s <code class="docutils literal notranslate"><span class="pre">__gt__</span></code> method with x as a second argument, and x &lt; y will
just use the existing (non-rich) comparison mechanism.</p>
<p>The above mechanism is such that classes can get away with not
implementing either <code class="docutils literal notranslate"><span class="pre">__lt__</span></code> and <code class="docutils literal notranslate"><span class="pre">__le__</span></code> or <code class="docutils literal notranslate"><span class="pre">__gt__</span></code> and
<code class="docutils literal notranslate"><span class="pre">__ge__</span></code>. Further smarts could have been added to the comparison
mechanism, but this limited set of allowed “swaps” was chosen
because it doesnt require the infrastructure to do any processing
(negation) of return values. The choice of six special methods was
made over a single (e.g. <code class="docutils literal notranslate"><span class="pre">__richcmp__</span></code>) method to allow the
dispatching on the opcode to be performed at the level of the C
implementation rather than the user-defined method.</p>
</li>
<li>Addition of an optional argument to the builtin <code class="docutils literal notranslate"><span class="pre">cmp()</span></code><p>The builtin <code class="docutils literal notranslate"><span class="pre">cmp()</span></code> is still used for simple comparisons. For rich
comparisons, it is called with a third argument, one of “&lt;”, “&lt;=”,
&gt;”, “&gt;=”, “==”, “!=”, “&lt;&gt;” (the last two have the same
meaning). When called with one of these strings as the third
argument, <code class="docutils literal notranslate"><span class="pre">cmp()</span></code> can return any Python object. Otherwise, it can
only return -1, 0 or 1 as before.</p>
</li>
</ol>
</section>
<section id="chained-comparisons">
<h3><a class="toc-backref" href="#chained-comparisons" role="doc-backlink">Chained Comparisons</a></h3>
<section id="problem">
<h4><a class="toc-backref" href="#problem" role="doc-backlink">Problem</a></h4>
<p>It would be nice to allow objects for which the comparison returns
something other than -1, 0, or 1 to be used in chained
comparisons, such as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">z</span>
</pre></div>
</div>
<p>Currently, this is interpreted by Python as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">temp1</span> <span class="o">=</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">y</span>
<span class="k">if</span> <span class="n">temp1</span><span class="p">:</span>
<span class="k">return</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">z</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">temp1</span>
</pre></div>
</div>
<p>Note that this requires testing the truth value of the result of
comparisons, with potential “shortcutting” of the right-side
comparison testings. In other words, the truth-value of the result
of the result of the comparison determines the result of a chained
operation. This is problematic in the case of arrays, since if x,
y and z are three arrays, then the user expects:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">z</span>
</pre></div>
</div>
<p>to be an array of 0s and 1s where 1s are in the locations
corresponding to the elements of y which are between the
corresponding elements in x and z. In other words, the right-hand
side must be evaluated regardless of the result of x &lt; y, which is
incompatible with the mechanism currently in use by the parser.</p>
</section>
<section id="solution">
<h4><a class="toc-backref" href="#solution" role="doc-backlink">Solution</a></h4>
<p>Guido mentioned that one possible way out would be to change the
code generated by chained comparisons to allow arrays to be
chained-compared intelligently. What follows is a mixture of his
idea and my suggestions. The code generated for x &lt; y &lt; z would be
equivalent to:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">temp1</span> <span class="o">=</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">y</span>
<span class="k">if</span> <span class="n">temp1</span><span class="p">:</span>
<span class="n">temp2</span> <span class="o">=</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">z</span>
<span class="k">return</span> <span class="n">boolean_combine</span><span class="p">(</span><span class="n">temp1</span><span class="p">,</span> <span class="n">temp2</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">temp1</span>
</pre></div>
</div>
<p>where boolean_combine is a new function which does something like
the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">boolean_combine</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="s1">&#39;__boolean_and__&#39;</span><span class="p">)</span> <span class="ow">or</span> \
<span class="nb">hasattr</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="s1">&#39;__boolean_and__&#39;</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="n">a</span><span class="o">.</span><span class="n">__boolean_and__</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">return</span> <span class="n">b</span><span class="o">.</span><span class="n">__boolean_and__</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span> <span class="c1"># standard behavior</span>
<span class="k">if</span> <span class="n">a</span><span class="p">:</span>
<span class="k">return</span> <span class="n">b</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">0</span>
</pre></div>
</div>
<p>where the <code class="docutils literal notranslate"><span class="pre">__boolean_and__</span></code> special method is implemented for
C-level types by another value of the third argument to the
richcmp function. This method would perform a boolean comparison
of the arrays (currently implemented in the umath module as the
logical_and ufunc).</p>
<p>Thus, objects returned by rich comparisons should always test
true, but should define another special method which creates
boolean combinations of them and their argument.</p>
<p>This solution has the advantage of allowing chained comparisons to
work for arrays, but the disadvantage that it requires comparison
arrays to always return true (in an ideal world, Id have them
always raise an exception on truth testing, since the meaning of
testing “if a&gt;b:” is massively ambiguous.</p>
<p>The inlining already present which deals with integer comparisons
would still apply, resulting in no performance cost for the most
common cases.</p>
</section>
</section>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0207.rst">https://github.com/python/peps/blob/main/peps/pep-0207.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0207.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#previous-work">Previous Work</a></li>
<li><a class="reference internal" href="#concerns">Concerns</a></li>
<li><a class="reference internal" href="#proposed-resolutions">Proposed Resolutions</a></li>
<li><a class="reference internal" href="#implementation-proposal">Implementation Proposal</a><ul>
<li><a class="reference internal" href="#c-api">C API</a></li>
<li><a class="reference internal" href="#changes-to-the-interpreter">Changes to the interpreter</a></li>
<li><a class="reference internal" href="#classes">Classes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#appendix">Appendix</a></li>
<li><a class="reference internal" href="#id1">Abstract</a></li>
<li><a class="reference internal" href="#id2">Motivation</a></li>
<li><a class="reference internal" href="#current-state-of-affairs">Current State of Affairs</a><ul>
<li><a class="reference internal" href="#proposed-mechanism">Proposed Mechanism</a></li>
<li><a class="reference internal" href="#chained-comparisons">Chained Comparisons</a><ul>
<li><a class="reference internal" href="#problem">Problem</a></li>
<li><a class="reference internal" href="#solution">Solution</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0207.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

386
pep-0208/index.html Normal file
View File

@ -0,0 +1,386 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 208 Reworking the Coercion Model | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0208/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 208 Reworking the Coercion Model | peps.python.org'>
<meta property="og:description" content="Many Python types implement numeric operations. When the arguments of a numeric operation are of different types, the interpreter tries to coerce the arguments into a common type. The numeric operation is then performed using this common type. This P...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0208/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Many Python types implement numeric operations. When the arguments of a numeric operation are of different types, the interpreter tries to coerce the arguments into a common type. The numeric operation is then performed using this common type. This P...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 208</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 208 Reworking the Coercion Model</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Neil Schemenauer &lt;nas&#32;&#97;t&#32;arctrix.com&gt;, Marc-André Lemburg &lt;mal&#32;&#97;t&#32;lemburg.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">04-Dec-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#specification">Specification</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#credits">Credits</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Many Python types implement numeric operations. When the arguments of
a numeric operation are of different types, the interpreter tries to
coerce the arguments into a common type. The numeric operation is
then performed using this common type. This PEP proposes a new type
flag to indicate that arguments to a types numeric operations should
not be coerced. Operations that do not support the supplied types
indicate it by returning a new singleton object. Types which do not
set the type flag are handled in a backwards compatible manner.
Allowing operations handle different types is often simpler, more
flexible, and faster than having the interpreter do coercion.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>When implementing numeric or other related operations, it is often
desirable to provide not only operations between operands of one type
only, e.g. integer + integer, but to generalize the idea behind the
operation to other type combinations as well, e.g. integer + float.</p>
<p>A common approach to this mixed type situation is to provide a method
of “lifting” the operands to a common type (coercion) and then use
that types operand method as execution mechanism. Yet, this strategy
has a few drawbacks:</p>
<ul class="simple">
<li>the “lifting” process creates at least one new (temporary)
operand object,</li>
<li>since the coercion method is not being told about the operation
that is to follow, it is not possible to implement operation
specific coercion of types,</li>
<li>there is no elegant way to solve situations were a common type
is not at hand, and</li>
<li>the coercion method will always have to be called prior to the
operations method itself.</li>
</ul>
<p>A fix for this situation is obviously needed, since these drawbacks
make implementations of types needing these features very cumbersome,
if not impossible. As an example, have a look at the <code class="docutils literal notranslate"><span class="pre">DateTime</span></code> and
<code class="docutils literal notranslate"><span class="pre">DateTimeDelta</span></code> <a class="footnote-reference brackets" href="#id4" id="id1">[1]</a> types, the first being absolute, the second
relative. You can always add a relative value to an absolute one,
giving a new absolute value. Yet, there is no common type which the
existing coercion mechanism could use to implement that operation.</p>
<p>Currently, <code class="docutils literal notranslate"><span class="pre">PyInstance</span></code> types are treated specially by the interpreter
in that their numeric methods are passed arguments of different types.
Removing this special case simplifies the interpreter and allows other
types to implement numeric methods that behave like instance types.
This is especially useful for extension types like ExtensionClass.</p>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>Instead of using a central coercion method, the process of handling
different operand types is simply left to the operation. If the
operation finds that it cannot handle the given operand type
combination, it may return a special singleton as indicator.</p>
<p>Note that “numbers” (anything that implements the number protocol, or
part of it) written in Python already use the first part of this
strategy - it is the C level API that we focus on here.</p>
<p>To maintain nearly 100% backward compatibility we have to be very
careful to make numbers that dont know anything about the new
strategy (old style numbers) work just as well as those that expect
the new scheme (new style numbers). Furthermore, binary compatibility
is a must, meaning that the interpreter may only access and use new
style operations if the number indicates the availability of these.</p>
<p>A new style number is considered by the interpreter as such if and
only if it sets the type flag <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_CHECKTYPES</span></code>. The main
difference between an old style number and a new style one is that the
numeric slot functions can no longer assume to be passed arguments of
identical type. New style slots must check all arguments for proper
type and implement the necessary conversions themselves. This may seem
to cause more work on the behalf of the type implementor, but is in
fact no more difficult than writing the same kind of routines for an
old style coercion slot.</p>
<p>If a new style slot finds that it cannot handle the passed argument
type combination, it may return a new reference of the special
singleton <code class="docutils literal notranslate"><span class="pre">Py_NotImplemented</span></code> to the caller. This will cause the caller
to try the other operands operation slots until it finds a slot that
does implement the operation for the specific type combination. If
none of the possible slots succeed, it raises a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>.</p>
<p>To make the implementation easy to understand (the whole topic is
esoteric enough), a new layer in the handling of numeric operations is
introduced. This layer takes care of all the different cases that need
to be taken into account when dealing with all the possible
combinations of old and new style numbers. It is implemented by the
two static functions <code class="docutils literal notranslate"><span class="pre">binary_op()</span></code> and <code class="docutils literal notranslate"><span class="pre">ternary_op()</span></code>, which are both
internal functions that only the functions in Objects/abstract.c
have access to. The numeric API (<code class="docutils literal notranslate"><span class="pre">PyNumber_*</span></code>) is easy to adapt to
this new layer.</p>
<p>As a side-effect all numeric slots can be NULL-checked (this has to be
done anyway, so the added feature comes at no extra cost).</p>
<p>The scheme used by the layer to execute a binary operation is as
follows:</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">v</th>
<th class="head">w</th>
<th class="head">Action taken</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>new</td>
<td>new</td>
<td>v.op(v,w), w.op(v,w)</td>
</tr>
<tr class="row-odd"><td>new</td>
<td>old</td>
<td>v.op(v,w), coerce(v,w), v.op(v,w)</td>
</tr>
<tr class="row-even"><td>old</td>
<td>new</td>
<td>w.op(v,w), coerce(v,w), v.op(v,w)</td>
</tr>
<tr class="row-odd"><td>old</td>
<td>old</td>
<td>coerce(v,w), v.op(v,w)</td>
</tr>
</tbody>
</table>
<p>The indicated action sequence is executed from left to right until
either the operation succeeds and a valid result (!=
<code class="docutils literal notranslate"><span class="pre">Py_NotImplemented</span></code>) is returned or an exception is raised. Exceptions
are returned to the calling function as-is. If a slot returns
<code class="docutils literal notranslate"><span class="pre">Py_NotImplemented</span></code>, the next item in the sequence is executed.</p>
<p>Note that coerce(v,w) will use the old style <code class="docutils literal notranslate"><span class="pre">nb_coerce</span></code> slot methods
via a call to <code class="docutils literal notranslate"><span class="pre">PyNumber_Coerce()</span></code>.</p>
<p>Ternary operations have a few more cases to handle:</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">v</th>
<th class="head">w</th>
<th class="head">z</th>
<th class="head">Action taken</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>new</td>
<td>new</td>
<td>new</td>
<td>v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)</td>
</tr>
<tr class="row-odd"><td>new</td>
<td>old</td>
<td>new</td>
<td>v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)</td>
</tr>
<tr class="row-even"><td>old</td>
<td>new</td>
<td>new</td>
<td>w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)</td>
</tr>
<tr class="row-odd"><td>old</td>
<td>old</td>
<td>new</td>
<td>z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)</td>
</tr>
<tr class="row-even"><td>new</td>
<td>new</td>
<td>old</td>
<td>v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)</td>
</tr>
<tr class="row-odd"><td>new</td>
<td>old</td>
<td>old</td>
<td>v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)</td>
</tr>
<tr class="row-even"><td>old</td>
<td>new</td>
<td>old</td>
<td>w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)</td>
</tr>
<tr class="row-odd"><td>old</td>
<td>old</td>
<td>old</td>
<td>coerce(v,w,z), v.op(v,w,z)</td>
</tr>
</tbody>
</table>
<p>The same notes as above, except that coerce(v,w,z) actually does:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">z</span> <span class="o">!=</span> <span class="n">Py_None</span><span class="p">:</span>
<span class="n">coerce</span><span class="p">(</span><span class="n">v</span><span class="p">,</span><span class="n">w</span><span class="p">),</span> <span class="n">coerce</span><span class="p">(</span><span class="n">v</span><span class="p">,</span><span class="n">z</span><span class="p">),</span> <span class="n">coerce</span><span class="p">(</span><span class="n">w</span><span class="p">,</span><span class="n">z</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># treat z as absent variable</span>
<span class="n">coerce</span><span class="p">(</span><span class="n">v</span><span class="p">,</span><span class="n">w</span><span class="p">)</span>
</pre></div>
</div>
<p>The current implementation uses this scheme already (theres only one
ternary slot: <code class="docutils literal notranslate"><span class="pre">nb_pow(a,b,c))</span></code>.</p>
<p>Note that the numeric protocol is also used for some other related
tasks, e.g. sequence concatenation. These can also benefit from the
new mechanism by implementing right-hand operations for type
combinations that would otherwise fail to work. As an example, take
string concatenation: currently you can only do string + string. With
the new mechanism, a new string-like type could implement new_type +
string and string + new_type, even though strings dont know anything
about new_type.</p>
<p>Since comparisons also rely on coercion (every time you compare an
integer to a float, the integer is first converted to float and then
compared…), a new slot to handle numeric comparisons is needed:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span> <span class="o">*</span><span class="n">nb_cmp</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">v</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">w</span><span class="p">)</span>
</pre></div>
</div>
<p>This slot should compare the two objects and return an integer object
stating the result. Currently, this result integer may only be -1, 0, 1.
If the slot cannot handle the type combination, it may return a
reference to <code class="docutils literal notranslate"><span class="pre">Py_NotImplemented</span></code>. [XXX Note that this slot is still
in flux since it should take into account rich comparisons
(i.e. <a class="pep reference internal" href="../pep-0207/" title="PEP 207 Rich Comparisons">PEP 207</a>).]</p>
<p>Numeric comparisons are handled by a new numeric protocol API:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span> <span class="o">*</span><span class="n">PyNumber_Compare</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">v</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">w</span><span class="p">)</span>
</pre></div>
</div>
<p>This function compare the two objects as “numbers” and return an
integer object stating the result. Currently, this result integer may
only be -1, 0, 1. In case the operation cannot be handled by the given
objects, a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> is raised.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">PyObject_Compare()</span></code> API needs to adjusted accordingly to make use
of this new API.</p>
<p>Other changes include adapting some of the built-in functions (e.g.
<code class="docutils literal notranslate"><span class="pre">cmp()</span></code>) to use this API as well. Also, <code class="docutils literal notranslate"><span class="pre">PyNumber_CoerceEx()</span></code> will need to
check for new style numbers before calling the <code class="docutils literal notranslate"><span class="pre">nb_coerce</span></code> slot. New
style numbers dont provide a coercion slot and thus cannot be
explicitly coerced.</p>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>A preliminary patch for the CVS version of Python is available through
the Source Forge patch manager <a class="footnote-reference brackets" href="#id5" id="id2">[2]</a>.</p>
</section>
<section id="credits">
<h2><a class="toc-backref" href="#credits" role="doc-backlink">Credits</a></h2>
<p>This PEP and the patch are heavily based on work done by Marc-André
Lemburg <a class="footnote-reference brackets" href="#id6" id="id3">[3]</a>.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id4" role="doc-footnote">
<dt class="label" id="id4">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://www.lemburg.com/files/python/mxDateTime.html">http://www.lemburg.com/files/python/mxDateTime.html</a></aside>
<aside class="footnote brackets" id="id5" role="doc-footnote">
<dt class="label" id="id5">[<a href="#id2">2</a>]</dt>
<dd><a class="reference external" href="http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=102652&amp;group_id=5470">http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=102652&amp;group_id=5470</a></aside>
<aside class="footnote brackets" id="id6" role="doc-footnote">
<dt class="label" id="id6">[<a href="#id3">3</a>]</dt>
<dd><a class="reference external" href="http://www.lemburg.com/files/python/CoercionProposal.html">http://www.lemburg.com/files/python/CoercionProposal.html</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0208.rst">https://github.com/python/peps/blob/main/peps/pep-0208.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0208.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#specification">Specification</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#credits">Credits</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0208.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

746
pep-0209/index.html Normal file
View File

@ -0,0 +1,746 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 209 Multi-dimensional Arrays | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0209/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 209 Multi-dimensional Arrays | peps.python.org'>
<meta property="og:description" content="This PEP proposes a redesign and re-implementation of the multi-dimensional array module, Numeric, to make it easier to add new features and functionality to the module. Aspects of Numeric 2 that will receive special attention are efficient access to a...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0209/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP proposes a redesign and re-implementation of the multi-dimensional array module, Numeric, to make it easier to add new features and functionality to the module. Aspects of Numeric 2 that will receive special attention are efficient access to a...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 209</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 209 Multi-dimensional Arrays</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Paul Barrett &lt;barrett&#32;&#97;t&#32;stsci.edu&gt;, Travis Oliphant &lt;oliphant&#32;&#97;t&#32;ee.byu.edu&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">03-Jan-2001</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.2</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#design-and-implementation">Design and Implementation</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#implementation-steps">Implementation Steps</a></li>
<li><a class="reference internal" href="#incompatibilities">Incompatibilities</a></li>
<li><a class="reference internal" href="#appendices">Appendices</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#related-peps">Related PEPs</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated withdrawn admonition important">
<p class="admonition-title">Important</p>
<p>This PEP has been withdrawn.</p>
<p class="close-button">×</p>
<p></p>
</div>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP proposes a redesign and re-implementation of the
multi-dimensional array module, Numeric, to make it easier to add
new features and functionality to the module. Aspects of Numeric 2
that will receive special attention are efficient access to arrays
exceeding a gigabyte in size and composed of inhomogeneous data
structures or records. The proposed design uses four Python
classes: ArrayType, UFunc, Array, and ArrayView; and a low-level
C-extension module, _ufunc, to handle the array operations
efficiently. In addition, each array type has its own C-extension
module which defines the coercion rules, operations, and methods
for that type. This design enables new types, features, and
functionality to be added in a modular fashion. The new version
will introduce some incompatibilities with the current Numeric.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>Multi-dimensional arrays are commonly used to store and manipulate
data in science, engineering, and computing. Python currently has
an extension module, named Numeric (henceforth called Numeric 1),
which provides a satisfactory set of functionality for users
manipulating homogeneous arrays of data of moderate size (of order
10 MB). For access to larger arrays (of order 100 MB or more) of
possibly inhomogeneous data, the implementation of Numeric 1 is
inefficient and cumbersome. In the future, requests by the
Numerical Python community for additional functionality is also
likely as PEPs 211: Adding New Linear Operators to Python, and
225: Elementwise/Objectwise Operators illustrate.</p>
</section>
<section id="proposal">
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
<p>This proposal recommends a re-design and re-implementation of
Numeric 1, henceforth called Numeric 2, which will enable new
types, features, and functionality to be added in an easy and
modular manner. The initial design of Numeric 2 should focus on
providing a generic framework for manipulating arrays of various
types and should enable a straightforward mechanism for adding new
array types and UFuncs. Functional methods that are more specific
to various disciplines can then be layered on top of this core.
This new module will still be called Numeric and most of the
behavior found in Numeric 1 will be preserved.</p>
<p>The proposed design uses four Python classes: ArrayType, UFunc,
Array, and ArrayView; and a low-level C-extension module to handle
the array operations efficiently. In addition, each array type
has its own C-extension module which defines the coercion rules,
operations, and methods for that type. At a later date, when core
functionality is stable, some Python classes can be converted to
C-extension types.</p>
<p>Some planned features are:</p>
<ol class="arabic">
<li>Improved memory usage<p>This feature is particularly important when handling large arrays
and can produce significant improvements in performance as well as
memory usage. We have identified several areas where memory usage
can be improved:</p>
<ol class="loweralpha">
<li>Use a local coercion model<p>Instead of using Pythons global coercion model which creates
temporary arrays, Numeric 2, like Numeric 1, will implement a
local coercion model as described in <a class="pep reference internal" href="../pep-0208/" title="PEP 208 Reworking the Coercion Model">PEP 208</a> which defers the
responsibility of coercion to the operator. By using internal
buffers, a coercion operation can be done for each array
(including output arrays), if necessary, at the time of the
operation. Benchmarks <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a> have shown that performance is at
most degraded only slightly and is improved in cases where the
internal buffers are less than the L2 cache size and the
processor is under load. To avoid array coercion altogether,
C functions having arguments of mixed type are allowed in
Numeric 2.</p>
</li>
<li>Avoid creation of temporary arrays<p>In complex array expressions (i.e. having more than one
operation), each operation will create a temporary array which
will be used and then deleted by the succeeding operation. A
better approach would be to identify these temporary arrays
and reuse their data buffers when possible, namely when the
array shape and type are the same as the temporary array being
created. This can be done by checking the temporary arrays
reference count. If it is 1, then it will be deleted once the
operation is done and is a candidate for reuse.</p>
</li>
<li>Optional use of memory-mapped files<p>Numeric users sometimes need to access data from very large
files or to handle data that is greater than the available
memory. Memory-mapped arrays provide a mechanism to do this
by storing the data on disk while making it appear to be in
memory. Memory- mapped arrays should improve access to all
files by eliminating one of two copy steps during a file
access. Numeric should be able to access in-memory and
memory-mapped arrays transparently.</p>
</li>
<li>Record access<p>In some fields of science, data is stored in files as binary
records. For example, in astronomy, photon data is stored as a
1 dimensional list of photons in order of arrival time. These
records or C-like structures contain information about the
detected photon, such as its arrival time, its position on the
detector, and its energy. Each field may be of a different
type, such as char, int, or float. Such arrays introduce new
issues that must be dealt with, in particular byte alignment
or byte swapping may need to be performed for the numeric
values to be properly accessed (though byte swapping is also
an issue for memory mapped data). Numeric 2 is designed to
automatically handle alignment and representational issues
when data is accessed or operated on. There are two
approaches to implementing records; as either a derived array
class or a special array type, depending on your point-of-view.
We defer this discussion to the Open Issues section.</p>
</li>
</ol>
</li>
<li>Additional array types<p>Numeric 1 has 11 defined types: char, ubyte, sbyte, short, int,
long, float, double, cfloat, cdouble, and object. There are no
ushort, uint, or ulong types, nor are there more complex types
such as a bit type which is of use to some fields of science and
possibly for implementing masked-arrays. The design of Numeric 1
makes the addition of these and other types a difficult and
error-prone process. To enable the easy addition (and deletion)
of new array types such as a bit type described below, a re-design
of Numeric is necessary.</p>
<ol class="loweralpha">
<li>Bit type<p>The result of a rich comparison between arrays is an array of
boolean values. The result can be stored in an array of type
char, but this is an unnecessary waste of memory. A better
implementation would use a bit or boolean type, compressing
the array size by a factor of eight. This is currently being
implemented for Numeric 1 (by Travis Oliphant) and should be
included in Numeric 2.</p>
</li>
</ol>
</li>
<li>Enhanced array indexing syntax<p>The extended slicing syntax was added to Python to provide greater
flexibility when manipulating Numeric arrays by allowing
step-sizes greater than 1. This syntax works well as a shorthand
for a list of regularly spaced indices. For those situations
where a list of irregularly spaced indices are needed, an enhanced
array indexing syntax would allow 1-D arrays to be arguments.</p>
</li>
<li>Rich comparisons<p>The implementation of <a class="pep reference internal" href="../pep-0207/" title="PEP 207 Rich Comparisons">PEP 207</a>: Rich Comparisons in Python 2.1
provides additional flexibility when manipulating arrays. We
intend to implement this feature in Numeric 2.</p>
</li>
<li>Array broadcasting rules<p>When an operation between a scalar and an array is done, the
implied behavior is to create a new array having the same shape as
the array operand containing the scalar value. This is called
array broadcasting. It also works with arrays of lesser rank,
such as vectors. This implicit behavior is implemented in Numeric
1 and will also be implemented in Numeric 2.</p>
</li>
</ol>
</section>
<section id="design-and-implementation">
<h2><a class="toc-backref" href="#design-and-implementation" role="doc-backlink">Design and Implementation</a></h2>
<p>The design of Numeric 2 has four primary classes:</p>
<ol class="arabic">
<li>ArrayType:<p>This is a simple class that describes the fundamental properties
of an array-type, e.g. its name, its size in bytes, its coercion
relations with respect to other types, etc., e.g.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Int32</span> <span class="o">=</span> <span class="n">ArrayType</span><span class="p">(</span><span class="s1">&#39;Int32&#39;</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="s1">&#39;doc-string&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Its relation to the other types is defined when the C-extension
module for that type is imported. The corresponding Python code
is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Int32</span><span class="o">.</span><span class="n">astype</span><span class="p">[</span><span class="n">Real64</span><span class="p">]</span> <span class="o">=</span> <span class="n">Real64</span>
</pre></div>
</div>
<p>This says that the Real64 array-type has higher priority than the
Int32 array-type.</p>
<p>The following attributes and methods are proposed for the core
implementation. Additional attributes can be added on an
individual basis, e.g. .bitsize or .bitstrides for the bit type.</p>
<p>Attributes:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">.</span><span class="n">name</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">g</span><span class="o">.</span> <span class="s2">&quot;Int32&quot;</span><span class="p">,</span> <span class="s2">&quot;Float64&quot;</span><span class="p">,</span> <span class="n">etc</span><span class="o">.</span>
<span class="o">.</span><span class="n">typecode</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">g</span><span class="o">.</span> <span class="s1">&#39;i&#39;</span><span class="p">,</span> <span class="s1">&#39;f&#39;</span><span class="p">,</span> <span class="n">etc</span><span class="o">.</span>
<span class="p">(</span><span class="k">for</span> <span class="n">backward</span> <span class="n">compatibility</span><span class="p">)</span>
<span class="o">.</span><span class="n">size</span> <span class="p">(</span><span class="ow">in</span> <span class="nb">bytes</span><span class="p">):</span> <span class="n">e</span><span class="o">.</span><span class="n">g</span><span class="o">.</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="n">etc</span><span class="o">.</span>
<span class="o">.</span><span class="n">array_rules</span> <span class="p">(</span><span class="n">mapping</span><span class="p">):</span> <span class="n">rules</span> <span class="n">between</span> <span class="n">array</span> <span class="n">types</span>
<span class="o">.</span><span class="n">pyobj_rules</span> <span class="p">(</span><span class="n">mapping</span><span class="p">):</span> <span class="n">rules</span> <span class="n">between</span> <span class="n">array</span> <span class="ow">and</span> <span class="n">python</span> <span class="n">types</span>
<span class="o">.</span><span class="n">doc</span><span class="p">:</span> <span class="n">documentation</span> <span class="n">string</span>
</pre></div>
</div>
<p>Methods:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="fm">__init__</span><span class="p">():</span> <span class="n">initialization</span>
<span class="fm">__del__</span><span class="p">():</span> <span class="n">destruction</span>
<span class="fm">__repr__</span><span class="p">():</span> <span class="n">representation</span>
</pre></div>
</div>
<p>C-API: This still needs to be fleshed-out.</p>
</li>
<li>UFunc:<p>This class is the heart of Numeric 2. Its design is similar to
that of ArrayType in that the UFunc creates a singleton callable
object whose attributes are name, total and input number of
arguments, a document string, and an empty CFunc dictionary; e.g.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">add</span> <span class="o">=</span> <span class="n">UFunc</span><span class="p">(</span><span class="s1">&#39;add&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="s1">&#39;doc-string&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>When defined the add instance has no C functions associated with
it and therefore can do no work. The CFunc dictionary is
populated or registered later when the C-extension module for an
array-type is imported. The arguments of the register method are:
function name, function descriptor, and the CUFunc object. The
corresponding Python code is</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">add</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="s1">&#39;add&#39;</span><span class="p">,</span> <span class="p">(</span><span class="n">Int32</span><span class="p">,</span> <span class="n">Int32</span><span class="p">,</span> <span class="n">Int32</span><span class="p">),</span> <span class="n">cfunc</span><span class="o">-</span><span class="n">add</span><span class="p">)</span>
</pre></div>
</div>
<p>In the initialization function of an array type module, e.g.
Int32, there are two C API functions: one to initialize the
coercion rules and the other to register the CFunc objects.</p>
<p>When an operation is applied to some arrays, the <code class="docutils literal notranslate"><span class="pre">__call__</span></code> method
is invoked. It gets the type of each array (if the output array
is not given, it is created from the coercion rules) and checks
the CFunc dictionary for a key that matches the argument types.
If it exists the operation is performed immediately, otherwise the
coercion rules are used to search for a related operation and set
of conversion functions. The <code class="docutils literal notranslate"><span class="pre">__call__</span></code> method then invokes a
compute method written in C to iterate over slices of each array,
namely:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">_ufunc</span><span class="o">.</span><span class="n">compute</span><span class="p">(</span><span class="nb">slice</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">swap</span><span class="p">,</span> <span class="n">conv</span><span class="p">)</span>
</pre></div>
</div>
<p>The func argument is a CFuncObject, while the swap and conv
arguments are lists of CFuncObjects for those arrays needing pre- or
post-processing, otherwise None is used. The data argument is
a list of buffer objects, and the slice argument gives the number
of iterations for each dimension along with the buffer offset and
step size for each array and each dimension.</p>
<p>We have predefined several UFuncs for use by the <code class="docutils literal notranslate"><span class="pre">__call__</span></code> method:
cast, swap, getobj, and setobj. The cast and swap functions do
coercion and byte-swapping, respectively and the getobj and setobj
functions do coercion between Numeric arrays and Python sequences.</p>
<p>The following attributes and methods are proposed for the core
implementation.</p>
<p>Attributes:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">.</span><span class="n">name</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">g</span><span class="o">.</span> <span class="s2">&quot;add&quot;</span><span class="p">,</span> <span class="s2">&quot;subtract&quot;</span><span class="p">,</span> <span class="n">etc</span><span class="o">.</span>
<span class="o">.</span><span class="n">nargs</span><span class="p">:</span> <span class="n">number</span> <span class="n">of</span> <span class="n">total</span> <span class="n">arguments</span>
<span class="o">.</span><span class="n">iargs</span><span class="p">:</span> <span class="n">number</span> <span class="n">of</span> <span class="nb">input</span> <span class="n">arguments</span>
<span class="o">.</span><span class="n">cfuncs</span> <span class="p">(</span><span class="n">mapping</span><span class="p">):</span> <span class="n">the</span> <span class="nb">set</span> <span class="n">C</span> <span class="n">functions</span>
<span class="o">.</span><span class="n">doc</span><span class="p">:</span> <span class="n">documentation</span> <span class="n">string</span>
</pre></div>
</div>
<p>Methods:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="fm">__init__</span><span class="p">():</span> <span class="n">initialization</span>
<span class="fm">__del__</span><span class="p">():</span> <span class="n">destruction</span>
<span class="fm">__repr__</span><span class="p">():</span> <span class="n">representation</span>
<span class="fm">__call__</span><span class="p">():</span> <span class="n">look</span><span class="o">-</span><span class="n">up</span> <span class="ow">and</span> <span class="n">dispatch</span> <span class="n">method</span>
<span class="n">initrule</span><span class="p">():</span> <span class="n">initialize</span> <span class="n">coercion</span> <span class="n">rule</span>
<span class="n">uninitrule</span><span class="p">():</span> <span class="n">uninitialize</span> <span class="n">coercion</span> <span class="n">rule</span>
<span class="n">register</span><span class="p">():</span> <span class="n">register</span> <span class="n">a</span> <span class="n">CUFunc</span>
<span class="n">unregister</span><span class="p">():</span> <span class="n">unregister</span> <span class="n">a</span> <span class="n">CUFunc</span>
</pre></div>
</div>
<p>C-API: This still needs to be fleshed-out.</p>
</li>
<li>Array:<p>This class contains information about the array, such as shape,
type, endian-ness of the data, etc.. Its operators, +, -,
etc. just invoke the corresponding UFunc function, e.g.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__add__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="n">ufunc</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">)</span>
</pre></div>
</div>
<p>The following attributes, methods, and functions are proposed for
the core implementation.</p>
<p>Attributes:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">.</span><span class="n">shape</span><span class="p">:</span> <span class="n">shape</span> <span class="n">of</span> <span class="n">the</span> <span class="n">array</span>
<span class="o">.</span><span class="n">format</span><span class="p">:</span> <span class="nb">type</span> <span class="n">of</span> <span class="n">the</span> <span class="n">array</span>
<span class="o">.</span><span class="n">real</span> <span class="p">(</span><span class="n">only</span> <span class="nb">complex</span><span class="p">):</span> <span class="n">real</span> <span class="n">part</span> <span class="n">of</span> <span class="n">a</span> <span class="nb">complex</span> <span class="n">array</span>
<span class="o">.</span><span class="n">imag</span> <span class="p">(</span><span class="n">only</span> <span class="nb">complex</span><span class="p">):</span> <span class="n">imaginary</span> <span class="n">part</span> <span class="n">of</span> <span class="n">a</span> <span class="nb">complex</span> <span class="n">array</span>
</pre></div>
</div>
<p>Methods:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="fm">__init__</span><span class="p">():</span> <span class="n">initialization</span>
<span class="fm">__del__</span><span class="p">():</span> <span class="n">destruction</span>
<span class="n">__repr_</span><span class="p">():</span> <span class="n">representation</span>
<span class="fm">__str__</span><span class="p">():</span> <span class="n">pretty</span> <span class="n">representation</span>
<span class="n">__cmp__</span><span class="p">():</span> <span class="n">rich</span> <span class="n">comparison</span>
<span class="fm">__len__</span><span class="p">():</span>
<span class="fm">__getitem__</span><span class="p">():</span>
<span class="fm">__setitem__</span><span class="p">():</span>
<span class="n">__getslice__</span><span class="p">():</span>
<span class="n">__setslice__</span><span class="p">():</span>
<span class="n">numeric</span> <span class="n">methods</span><span class="p">:</span>
<span class="n">copy</span><span class="p">():</span> <span class="n">copy</span> <span class="n">of</span> <span class="n">array</span>
<span class="n">aslist</span><span class="p">():</span> <span class="n">create</span> <span class="nb">list</span> <span class="kn">from</span> <span class="nn">array</span>
<span class="n">asstring</span><span class="p">():</span> <span class="n">create</span> <span class="n">string</span> <span class="kn">from</span> <span class="nn">array</span>
</pre></div>
</div>
<p>Functions:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">fromlist</span><span class="p">():</span> <span class="n">create</span> <span class="n">array</span> <span class="kn">from</span> <span class="nn">sequence</span>
<span class="n">fromstring</span><span class="p">():</span> <span class="n">create</span> <span class="n">array</span> <span class="kn">from</span> <span class="nn">string</span>
<span class="n">array</span><span class="p">():</span> <span class="n">create</span> <span class="n">array</span> <span class="k">with</span> <span class="n">shape</span> <span class="ow">and</span> <span class="n">value</span>
<span class="n">concat</span><span class="p">():</span> <span class="n">concatenate</span> <span class="n">two</span> <span class="n">arrays</span>
<span class="n">resize</span><span class="p">():</span> <span class="n">resize</span> <span class="n">array</span>
</pre></div>
</div>
<p>C-API: This still needs to be fleshed-out.</p>
</li>
<li>ArrayView<p>This class is similar to the Array class except that the reshape
and flat methods will raise exceptions, since non-contiguous
arrays cannot be reshaped or flattened using just pointer and
step-size information.</p>
<p>C-API: This still needs to be fleshed-out.</p>
</li>
<li>C-extension modules:<p>Numeric2 will have several C-extension modules.</p>
<ol class="loweralpha">
<li>_ufunc:<p>The primary module of this set is the _ufuncmodule.c. The
intention of this module is to do the bare minimum,
i.e. iterate over arrays using a specified C function. The
interface of these functions is the same as Numeric 1, i.e.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="p">(</span><span class="o">*</span><span class="n">CFunc</span><span class="p">)(</span><span class="n">char</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="nb">int</span> <span class="o">*</span><span class="n">steps</span><span class="p">,</span> <span class="nb">int</span> <span class="n">repeat</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">func</span><span class="p">);</span>
</pre></div>
</div>
<p>and their functionality is expected to be the same, i.e. they
iterate over the inner-most dimension.</p>
<p>The following attributes and methods are proposed for the core
implementation.</p>
<p>Attributes:</p>
<p>Methods:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">compute</span><span class="p">():</span>
</pre></div>
</div>
<p>C-API: This still needs to be fleshed-out.</p>
</li>
<li>_int32, _real64, etc.:<p>There will also be C-extension modules for each array type,
e.g. _int32module.c, _real64module.c, etc. As mentioned
previously, when these modules are imported by the UFunc
module, they will automatically register their functions and
coercion rules. New or improved versions of these modules can
be easily implemented and used without affecting the rest of
Numeric 2.</p>
</li>
</ol>
</li>
</ol>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
<ol class="arabic">
<li>Does slicing syntax default to copy or view behavior?<p>The default behavior of Python is to return a copy of a sub-list
or tuple when slicing syntax is used, whereas Numeric 1 returns a
view into the array. The choice made for Numeric 1 is apparently
for reasons of performance: the developers wish to avoid the
penalty of allocating and copying the data buffer during each
array operation and feel that the need for a deep copy of an array
to be rare. Yet, some have argued that Numerics slice notation
should also have copy behavior to be consistent with Python lists.
In this case the performance penalty associated with copy behavior
can be minimized by implementing copy-on-write. This scheme has
both arrays sharing one data buffer (as in view behavior) until
either array is assigned new data at which point a copy of the
data buffer is made. View behavior would then be implemented by
an ArrayView class, whose behavior be similar to Numeric 1 arrays,
i.e. .shape is not settable for non-contiguous arrays. The use of
an ArrayView class also makes explicit what type of data the array
contains.</p>
</li>
<li>Does item syntax default to copy or view behavior?<p>A similar question arises with the item syntax. For example, if
<code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">=</span> <span class="pre">[[0,1,2],</span> <span class="pre">[3,4,5]]</span></code> and <code class="docutils literal notranslate"><span class="pre">b</span> <span class="pre">=</span> <span class="pre">a[0]</span></code>, then changing <code class="docutils literal notranslate"><span class="pre">b[0]</span></code> also changes
<code class="docutils literal notranslate"><span class="pre">a[0][0]</span></code>, because <code class="docutils literal notranslate"><span class="pre">a[0]</span></code> is a reference or view of the first row of a.
Therefore, if c is a 2-d array, it would appear that <code class="docutils literal notranslate"><span class="pre">c[i]</span></code>
should return a 1-d array which is a view into, instead of a copy
of, c for consistency. Yet, <code class="docutils literal notranslate"><span class="pre">c[i]</span></code> can be considered just a
shorthand for <code class="docutils literal notranslate"><span class="pre">c[i,:]</span></code> which would imply copy behavior assuming
slicing syntax returns a copy. Should Numeric 2 behave the same
way as lists and return a view or should it return a copy.</p>
</li>
<li>How is scalar coercion implemented?<p>Python has fewer numeric types than Numeric which can cause
coercion problems. For example, when multiplying a Python scalar
of type float and a Numeric array of type float, the Numeric array
is converted to a double, since the Python float type is actually
a double. This is often not the desired behavior, since the
Numeric array will be doubled in size which is likely to be
annoying, particularly for very large arrays. We prefer that the
array type trumps the python type for the same type class, namely
integer, float, and complex. Therefore, an operation between a
Python integer and an Int16 (short) array will return an Int16
array. Whereas an operation between a Python float and an Int16
array would return a Float64 (double) array. Operations between
two arrays use normal coercion rules.</p>
</li>
<li>How is integer division handled?<p>In a future version of Python, the behavior of integer division
will change. The operands will be converted to floats, so the
result will be a float. If we implement the proposed scalar
coercion rules where arrays have precedence over Python scalars,
then dividing an array by an integer will return an integer array
and will not be consistent with a future version of Python which
would return an array of type double. Scientific programmers are
familiar with the distinction between integer and float-point
division, so should Numeric 2 continue with this behavior?</p>
</li>
<li>How should records be implemented?<p>There are two approaches to implementing records depending on your
point-of-view. The first is two divide arrays into separate
classes depending on the behavior of their types. For example,
numeric arrays are one class, strings a second, and records a
third, because the range and type of operations of each class
differ. As such, a record array is not a new type, but a
mechanism for a more flexible form of array. To easily access and
manipulate such complex data, the class is comprised of numeric
arrays having different byte offsets into the data buffer. For
example, one might have a table consisting of an array of Int16,
Real32 values. Two numeric arrays, one with an offset of 0 bytes
and a stride of 6 bytes to be interpreted as Int16, and one with an
offset of 2 bytes and a stride of 6 bytes to be interpreted as
Real32 would represent the record array. Both numeric arrays
would refer to the same data buffer, but have different offset and
stride attributes, and a different numeric type.</p>
<p>The second approach is to consider a record as one of many array
types, albeit with fewer, and possibly different, array operations
than for numeric arrays. This approach considers an array type to
be a mapping of a fixed-length string. The mapping can either be
simple, like integer and floating-point numbers, or complex, like
a complex number, a byte string, and a C-structure. The record
type effectively merges the struct and Numeric modules into a
multi-dimensional struct array. This approach implies certain
changes to the array interface. For example, the typecode
keyword argument should probably be changed to the more
descriptive format keyword.</p>
<ol class="loweralpha">
<li>How are record semantics defined and implemented?<p>Which ever implementation approach is taken for records, the
syntax and semantics of how they are to be accessed and
manipulated must be decided, if one wishes to have access to
sub-fields of records. In this case, the record type can
essentially be considered an inhomogeneous list, like a tuple
returned by the unpack method of the struct module; and a 1-d
array of records may be interpreted as a 2-d array with the
second dimension being the index into the list of fields.
This enhanced array semantics makes access to an array of one
or more of the fields easy and straightforward. It also
allows a user to do array operations on a field in a natural
and intuitive way. If we assume that records are implemented
as an array type, then last dimension defaults to 0 and can
therefore be neglected for arrays comprised of simple types,
like numeric.</p>
</li>
</ol>
</li>
<li>How are masked-arrays implemented?<p>Masked-arrays in Numeric 1 are implemented as a separate array
class. With the ability to add new array types to Numeric 2, it
is possible that masked-arrays in Numeric 2 could be implemented
as a new array type instead of an array class.</p>
</li>
<li>How are numerical errors handled (IEEE floating-point errors in
particular)?<p>It is not clear to the proposers (Paul Barrett and Travis
Oliphant) what is the best or preferred way of handling errors.
Since most of the C functions that do the operation, iterate over
the inner-most (last) dimension of the array. This dimension
could contain a thousand or more items having one or more errors
of differing type, such as divide-by-zero, underflow, and
overflow. Additionally, keeping track of these errors may come at
the expense of performance. Therefore, we suggest several
options:</p>
<ol class="loweralpha simple">
<li>Print a message of the most severe error, leaving it to
the user to locate the errors.</li>
<li>Print a message of all errors that occurred and the number
of occurrences, leaving it to the user to locate the errors.</li>
<li>Print a message of all errors that occurred and a list of
where they occurred.</li>
<li>Or use a hybrid approach, printing only the most severe
error, yet keeping track of what and where the errors
occurred. This would allow the user to locate the errors
while keeping the error message brief.</li>
</ol>
</li>
<li>What features are needed to ease the integration of FORTRAN
libraries and code?</li>
</ol>
<p>It would be a good idea at this stage to consider how to ease the
integration of FORTRAN libraries and user code in Numeric 2.</p>
</section>
<section id="implementation-steps">
<h2><a class="toc-backref" href="#implementation-steps" role="doc-backlink">Implementation Steps</a></h2>
<ol class="arabic">
<li>Implement basic UFunc capability<ol class="loweralpha">
<li>Minimal Array class:<p>Necessary class attributes and methods, e.g. .shape, .data,
.type, etc.</p>
</li>
<li>Minimal ArrayType class:<p>Int32, Real64, Complex64, Char, Object</p>
</li>
<li>Minimal UFunc class:<p>UFunc instantiation, CFunction registration, UFunc call for
1-D arrays including the rules for doing alignment,
byte-swapping, and coercion.</p>
</li>
<li>Minimal C-extension module:<p>_UFunc, which does the innermost array loop in C.</p>
<p>This step implements whatever is needed to do: c = add(a, b)
where a, b, and c are 1-D arrays. It teaches us how to add
new UFuncs, to coerce the arrays, to pass the necessary
information to a C iterator method and to do the actually
computation.</p>
</li>
</ol>
</li>
<li>Continue enhancing the UFunc iterator and Array class<ol class="loweralpha simple">
<li>Implement some access methods for the Array class:
print, repr, getitem, setitem, etc.</li>
<li>Implement multidimensional arrays</li>
<li>Implement some of basic Array methods using UFuncs:
+, -, *, /, etc.</li>
<li>Enable UFuncs to use Python sequences.</li>
</ol>
</li>
<li>Complete the standard UFunc and Array class behavior<ol class="loweralpha simple">
<li>Implement getslice and setslice behavior</li>
<li>Work on Array broadcasting rules</li>
<li>Implement Record type</li>
</ol>
</li>
<li>Add additional functionality<ol class="loweralpha simple">
<li>Add more UFuncs</li>
<li>Implement buffer or mmap access</li>
</ol>
</li>
</ol>
</section>
<section id="incompatibilities">
<h2><a class="toc-backref" href="#incompatibilities" role="doc-backlink">Incompatibilities</a></h2>
<p>The following is a list of incompatibilities in behavior between
Numeric 1 and Numeric 2.</p>
<ol class="arabic">
<li>Scalar coercion rules<p>Numeric 1 has single set of coercion rules for array and Python
numeric types. This can cause unexpected and annoying problems
during the calculation of an array expression. Numeric 2 intends
to overcome these problems by having two sets of coercion rules:
one for arrays and Python numeric types, and another just for
arrays.</p>
</li>
<li>No savespace attribute<p>The savespace attribute in Numeric 1 makes arrays with this
attribute set take precedence over those that do not have it set.
Numeric 2 will not have such an attribute and therefore normal
array coercion rules will be in effect.</p>
</li>
<li>Slicing syntax returns a copy<p>The slicing syntax in Numeric 1 returns a view into the original
array. The slicing behavior for Numeric 2 will be a copy. You
should use the ArrayView class to get a view into an array.</p>
</li>
<li>Boolean comparisons return a boolean array<p>A comparison between arrays in Numeric 1 results in a Boolean
scalar, because of current limitations in Python. The advent of
Rich Comparisons in Python 2.1 will allow an array of Booleans to
be returned.</p>
</li>
<li>Type characters are deprecated<p>Numeric 2 will have an ArrayType class composed of Type instances,
for example Int8, Int16, Int32, and Int for signed integers. The
typecode scheme in Numeric 1 will be available for backward
compatibility, but will be deprecated.</p>
</li>
</ol>
</section>
<section id="appendices">
<h2><a class="toc-backref" href="#appendices" role="doc-backlink">Appendices</a></h2>
<ol class="upperalpha">
<li>Implicit sub-arrays iteration<p>A computer animation is composed of a number of 2-D images or
frames of identical shape. By stacking these images into a single
block of memory, a 3-D array is created. Yet the operations to be
performed are not meant for the entire 3-D array, but on the set
of 2-D sub-arrays. In most array languages, each frame has to be
extracted, operated on, and then reinserted into the output array
using a for-like loop. The J language allows the programmer to
perform such operations implicitly by having a rank for the frame
and array. By default these ranks will be the same during the
creation of the array. It was the intention of the Numeric 1
developers to implement this feature, since it is based on the
language J. The Numeric 1 code has the required variables for
implementing this behavior, but was never implemented. We intend
to implement implicit sub-array iteration in Numeric 2, if the
array broadcasting rules found in Numeric 1 do not fully support
this behavior.</p>
</li>
</ol>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document is placed in the public domain.</p>
</section>
<section id="related-peps">
<h2><a class="toc-backref" href="#related-peps" role="doc-backlink">Related PEPs</a></h2>
<ul class="simple">
<li><a class="pep reference internal" href="../pep-0207/" title="PEP 207 Rich Comparisons">PEP 207</a>: Rich Comparisons
by Guido van Rossum and David Ascher</li>
<li><a class="pep reference internal" href="../pep-0208/" title="PEP 208 Reworking the Coercion Model">PEP 208</a>: Reworking the Coercion Model
by Neil Schemenauer and Marc-Andre Lemburg</li>
<li><a class="pep reference internal" href="../pep-0211/" title="PEP 211 Adding A New Outer Product Operator">PEP 211</a>: Adding New Linear Algebra Operators to Python
by Greg Wilson</li>
<li><a class="pep reference internal" href="../pep-0225/" title="PEP 225 Elementwise/Objectwise Operators">PEP 225</a>: Elementwise/Objectwise Operators
by Huaiyu Zhu</li>
<li><a class="pep reference internal" href="../pep-0228/" title="PEP 228 Reworking Pythons Numeric Model">PEP 228</a>: Reworking Pythons Numeric Model
by Moshe Zadka</li>
</ul>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd><ol class="upperalpha simple" start="16">
<li>Greenfield 2000. private communication.</li>
</ol>
</aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0209.rst">https://github.com/python/peps/blob/main/peps/pep-0209.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0209.rst">2024-04-14 13:35:25 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#design-and-implementation">Design and Implementation</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#implementation-steps">Implementation Steps</a></li>
<li><a class="reference internal" href="#incompatibilities">Incompatibilities</a></li>
<li><a class="reference internal" href="#appendices">Appendices</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#related-peps">Related PEPs</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0209.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

122
pep-0210/index.html Normal file
View File

@ -0,0 +1,122 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 210 Decoupling the Interpreter Loop | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0210/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 210 Decoupling the Interpreter Loop | peps.python.org'>
<meta property="og:description" content="Python Enhancement Proposals (PEPs)">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0210/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python Enhancement Proposals (PEPs)">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 210</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 210 Decoupling the Interpreter Loop</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">David Ascher &lt;davida&#32;&#97;t&#32;activestate.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">15-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<div class="pep-banner sticky-banner deprecated rejected admonition warning">
<p class="admonition-title">Warning</p>
<p>This PEP has been rejected.</p>
<p class="close-button">×</p>
<p></p>
</div>
</section>
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0210.rst">https://github.com/python/peps/blob/main/peps/pep-0210.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0210.rst">2024-04-14 13:35:25 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0210.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

306
pep-0211/index.html Normal file
View File

@ -0,0 +1,306 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 211 Adding A New Outer Product Operator | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0211/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 211 Adding A New Outer Product Operator | peps.python.org'>
<meta property="og:description" content="This PEP describes a proposal to define @ (pronounced “across”) as a new outer product operator in Python 2.2. When applied to sequences (or other iterable objects), this operator will combine their iterators, so that:">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0211/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes a proposal to define @ (pronounced “across”) as a new outer product operator in Python 2.2. When applied to sequences (or other iterable objects), this operator will combine their iterators, so that:">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 211</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 211 Adding A New Outer Product Operator</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Greg Wilson &lt;gvwilson&#32;&#97;t&#32;ddj.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">15-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#iterators">Iterators</a></li>
<li><a class="reference internal" href="#discussion">Discussion</a></li>
<li><a class="reference internal" href="#alternatives">Alternatives</a></li>
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated rejected admonition warning">
<p class="admonition-title">Warning</p>
<p>This PEP has been rejected.</p>
<p class="close-button">×</p>
<p>The approach in the later <a class="pep reference internal" href="../pep-0465/" title="PEP 465 A dedicated infix operator for matrix multiplication">PEP 465</a> was eventually accepted
in lieu of this PEP. The <a class="pep reference internal" href="../pep-0465/#rejected-alternatives-to-adding-a-new-operator" title="PEP 465 A dedicated infix operator for matrix multiplication § Rejected alternatives to adding a new operator">Rejected Ideas</a>
of that PEP explains the rationale in more detail.</p>
<p></p>
</div>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes a proposal to define <code class="docutils literal notranslate"><span class="pre">&#64;</span></code> (pronounced “across”)
as a new outer product operator in Python 2.2. When applied to
sequences (or other iterable objects), this operator will combine
their iterators, so that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span> <span class="ow">in</span> <span class="n">S</span> <span class="o">@</span> <span class="n">T</span><span class="p">:</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>will be equivalent to:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">S</span><span class="p">:</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">T</span><span class="p">:</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>Classes will be able to overload this operator using the special
methods <code class="docutils literal notranslate"><span class="pre">__across__</span></code>, <code class="docutils literal notranslate"><span class="pre">__racross__</span></code>, and <code class="docutils literal notranslate"><span class="pre">__iacross__</span></code>. In
particular, the new Numeric module (<a class="pep reference internal" href="../pep-0209/" title="PEP 209 Multi-dimensional Arrays">PEP 209</a>) will overload this
operator for multi-dimensional arrays to implement matrix
multiplication.</p>
</section>
<section id="background">
<h2><a class="toc-backref" href="#background" role="doc-backlink">Background</a></h2>
<p>Number-crunching is now just a small part of computing, but many
programmers — including many Python users — still need to
express complex mathematical operations in code. Most numerical
languages, such as APL, Fortran-90, MATLAB, IDL, and Mathematica,
therefore provide two forms of the common arithmetic operators.
One form works element-by-element, e.g. multiplies corresponding
elements of its matrix arguments. The other implements the
“mathematical” definition of that operation, e.g. performs
row-column matrix multiplication.</p>
<p>Zhu and Lielens have <a class="pep reference internal" href="../pep-0225/" title="PEP 225 Elementwise/Objectwise Operators">proposed</a> doubling up Pythons operators in
this way. Their proposal would create six new binary infix
operators, and six new in-place operators.</p>
<p>The original version of this proposal was much more conservative.
The author consulted the developers of GNU Octave <a class="footnote-reference brackets" href="#id5" id="id1">[1]</a>, an open
source clone of MATLAB. Its developers agreed that providing an
infix operator for matrix multiplication was important: numerical
programmers really do care whether they have to write <code class="docutils literal notranslate"><span class="pre">mmul(A,B)</span></code>
instead of <code class="docutils literal notranslate"><span class="pre">A</span> <span class="pre">op</span> <span class="pre">B</span></code>.</p>
<p>On the other hand, when asked how important it was to have infix
operators for matrix solution and other operations, Prof. James
Rawlings replied <a class="footnote-reference brackets" href="#id6" id="id2">[2]</a>:</p>
<blockquote>
<div>I DONT think its a must have, and I do a lot of matrix
inversion. I cannot remember if its <code class="docutils literal notranslate"><span class="pre">A\b</span></code> or <code class="docutils literal notranslate"><span class="pre">b\A</span></code> so I always
write <code class="docutils literal notranslate"><span class="pre">inv(A)*b</span></code> instead. I recommend dropping <code class="docutils literal notranslate"><span class="pre">\</span></code>.</div></blockquote>
<p>Based on this discussion, and feedback from students at the US
national laboratories and elsewhere, we recommended adding only
one new operator, for matrix multiplication, to Python.</p>
</section>
<section id="iterators">
<h2><a class="toc-backref" href="#iterators" role="doc-backlink">Iterators</a></h2>
<p>The planned addition of iterators to Python 2.2 opens up a broader
scope for this proposal. As part of the discussion of <a class="pep reference internal" href="../pep-0201/" title="PEP 201 Lockstep Iteration">PEP 201</a>,
Lockstep Iteration, the author of this proposal conducted an
informal usability experiment <a class="footnote-reference brackets" href="#id7" id="id3">[3]</a>. The results showed that users
are psychologically receptive to “cross-product” loop syntax. For
example, most users expected:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">S</span> <span class="o">=</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">]</span>
<span class="n">T</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">S</span><span class="p">;</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">T</span><span class="p">:</span>
<span class="nb">print</span> <span class="n">x</span><span class="o">+</span><span class="n">y</span><span class="p">,</span>
</pre></div>
</div>
<p>to print <code class="docutils literal notranslate"><span class="pre">11</span> <span class="pre">12</span> <span class="pre">13</span> <span class="pre">21</span> <span class="pre">22</span> <span class="pre">23</span> <span class="pre">31</span> <span class="pre">32</span> <span class="pre">33</span></code>. We believe that users will
have the same reaction to:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="ow">in</span> <span class="n">S</span> <span class="o">@</span> <span class="n">T</span><span class="p">:</span>
<span class="nb">print</span> <span class="n">x</span><span class="o">+</span><span class="n">y</span>
</pre></div>
</div>
<p>i.e. that they will naturally interpret this as a tidy way to
write loop nests.</p>
<p>This is where iterators come in. Actually constructing the
cross-product of two (or more) sequences before executing the loop
would be very expensive. On the other hand, <code class="docutils literal notranslate"><span class="pre">&#64;</span></code> could be defined
to get its arguments iterators, and then create an outer iterator
which returns tuples of the values returned by the inner
iterators.</p>
</section>
<section id="discussion">
<h2><a class="toc-backref" href="#discussion" role="doc-backlink">Discussion</a></h2>
<ol class="arabic">
<li>Adding a named function “across” would have less impact on
Python than a new infix operator. However, this would not make
Python more appealing to numerical programmers, who really do
care whether they can write matrix multiplication using an
operator, or whether they have to write it as a function call.</li>
<li><code class="docutils literal notranslate"><span class="pre">&#64;</span></code> would have be chainable in the same way as comparison
operators, i.e.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="o">@</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span> <span class="o">@</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span>
</pre></div>
</div>
<p>would have to return <code class="docutils literal notranslate"><span class="pre">(1,</span> <span class="pre">3,</span> <span class="pre">5)</span> <span class="pre">...</span> <span class="pre">(2,</span> <span class="pre">4,</span> <span class="pre">6)</span></code>, and <em>not</em>
<code class="docutils literal notranslate"><span class="pre">((1,</span> <span class="pre">3),</span> <span class="pre">5)</span> <span class="pre">...</span> <span class="pre">((2,</span> <span class="pre">4),</span> <span class="pre">6)</span></code>. This should not require special
support from the parser, as the outer iterator created by the
first <code class="docutils literal notranslate"><span class="pre">&#64;</span></code> could easily be taught how to combine itself with
ordinary iterators.</p>
</li>
<li>There would have to be some way to distinguish restartable
iterators from ones that couldnt be restarted. For example,
if <code class="docutils literal notranslate"><span class="pre">S</span></code> is an input stream (e.g. a file), and <code class="docutils literal notranslate"><span class="pre">L</span></code> is a list, then <code class="docutils literal notranslate"><span class="pre">S</span>
<span class="pre">&#64;</span> <span class="pre">L</span></code> is straightforward, but <code class="docutils literal notranslate"><span class="pre">L</span> <span class="pre">&#64;</span> <span class="pre">S</span></code> is not, since iteration
through the stream cannot be repeated. This could be treated
as an error, or by having the outer iterator detect
non-restartable inner iterators and cache their values.</li>
<li>Whiteboard testing of this proposal in front of three novice
Python users (all of them experienced programmers) indicates
that users will expect:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s2">&quot;ab&quot;</span> <span class="o">@</span> <span class="s2">&quot;cd&quot;</span>
</pre></div>
</div>
<p>to return four strings, not four tuples of pairs of
characters. Opinion was divided on what:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="s2">&quot;b&quot;</span><span class="p">)</span> <span class="o">@</span> <span class="s2">&quot;cd&quot;</span>
</pre></div>
</div>
<p>ought to return…</p>
</li>
</ol>
</section>
<section id="alternatives">
<h2><a class="toc-backref" href="#alternatives" role="doc-backlink">Alternatives</a></h2>
<ol class="arabic">
<li>Do nothing — keep Python simple.<p>This is always the default choice.</p>
</li>
<li>Add a named function instead of an operator.<p>Python is not primarily a numerical language; it may not be worth
complexifying it for this special case. However, support for real
matrix multiplication <em>is</em> frequently requested, and the proposed
semantics for <code class="docutils literal notranslate"><span class="pre">&#64;</span></code> for built-in sequence types would simplify
expression of a very common idiom (nested loops).</p>
</li>
<li>Introduce prefixed forms of all existing operators, such as
<code class="docutils literal notranslate"><span class="pre">~*</span></code> and <code class="docutils literal notranslate"><span class="pre">~+</span></code>, as proposed in <a class="pep reference internal" href="../pep-0225/" title="PEP 225 Elementwise/Objectwise Operators">PEP 225</a>.<p>Our objections to this are that there isnt enough demand to
justify the additional complexity (see Rawlings comments <a class="footnote-reference brackets" href="#id6" id="id4">[2]</a>),
and that the proposed syntax fails the “low toner” readability
test.</p>
</li>
</ol>
</section>
<section id="acknowledgments">
<h2><a class="toc-backref" href="#acknowledgments" role="doc-backlink">Acknowledgments</a></h2>
<p>I am grateful to Huaiyu Zhu for initiating this discussion, and to
James Rawlings and students in various Python courses for their
discussions of what numerical programmers really care about.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id5" role="doc-footnote">
<dt class="label" id="id5">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://bevo.che.wisc.edu/octave/">http://bevo.che.wisc.edu/octave/</a></aside>
<aside class="footnote brackets" id="id6" role="doc-footnote">
<dt class="label" id="id6">[2]<em> (<a href='#id2'>1</a>, <a href='#id4'>2</a>) </em></dt>
<dd><a class="reference external" href="http://www.egroups.com/message/python-numeric/4">http://www.egroups.com/message/python-numeric/4</a></aside>
<aside class="footnote brackets" id="id7" role="doc-footnote">
<dt class="label" id="id7">[<a href="#id3">3</a>]</dt>
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2000-July/006427.html">https://mail.python.org/pipermail/python-dev/2000-July/006427.html</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0211.rst">https://github.com/python/peps/blob/main/peps/pep-0211.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0211.rst">2024-04-14 20:08:31 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#iterators">Iterators</a></li>
<li><a class="reference internal" href="#discussion">Discussion</a></li>
<li><a class="reference internal" href="#alternatives">Alternatives</a></li>
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0211.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

303
pep-0212/index.html Normal file
View File

@ -0,0 +1,303 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 212 Loop Counter Iteration | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0212/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 212 Loop Counter Iteration | peps.python.org'>
<meta property="og:description" content="This PEP describes the often proposed feature of exposing the loop counter in for-loops. This PEP tracks the status and ownership of this feature. It contains a description of the feature and outlines changes necessary to support the feature. This PE...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0212/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the often proposed feature of exposing the loop counter in for-loops. This PEP tracks the status and ownership of this feature. It contains a description of the feature and outlines changes necessary to support the feature. This PE...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 212</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 212 Loop Counter Iteration</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Peter Schneider-Kamp &lt;nowonder&#32;&#97;t&#32;nowonder.de&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">22-Aug-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#rejection-notice">Rejection Notice</a></li>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#loop-counter-iteration">Loop counter iteration</a></li>
<li><a class="reference internal" href="#the-proposed-solutions">The Proposed Solutions</a></li>
<li><a class="reference internal" href="#non-reserved-keyword-indexing">Non-reserved keyword <code class="docutils literal notranslate"><span class="pre">indexing</span></code></a></li>
<li><a class="reference internal" href="#built-in-functions-indices-and-irange">Built-in functions <code class="docutils literal notranslate"><span class="pre">indices</span></code> and <code class="docutils literal notranslate"><span class="pre">irange</span></code></a></li>
<li><a class="reference internal" href="#methods-for-sequence-objects">Methods for sequence objects</a></li>
<li><a class="reference internal" href="#implementations">Implementations</a></li>
<li><a class="reference internal" href="#backward-compatibility-issues">Backward Compatibility Issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<section id="rejection-notice">
<h2><a class="toc-backref" href="#rejection-notice" role="doc-backlink">Rejection Notice</a></h2>
<p>This PEP has been rejected. <code class="docutils literal notranslate"><span class="pre">enumerate()</span></code>, introduced in <a class="pep reference internal" href="../pep-0279/" title="PEP 279 The enumerate() built-in function">PEP 279</a>,
covers the use-case proposed in this PEP, and the PEP author has been
unreachable.</p>
</section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes the often proposed feature of exposing the loop
counter in for-loops. This PEP tracks the status and ownership of
this feature. It contains a description of the feature and
outlines changes necessary to support the feature. This PEP
summarizes discussions held in mailing list forums, and provides
URLs for further information, where appropriate. The CVS revision
history of this file contains the definitive historical record.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>Standard for-loops in Python iterate over the elements of a
sequence <a class="footnote-reference brackets" href="#id6" id="id1">[1]</a>. Often it is desirable to loop over the indices or
both the elements and the indices instead.</p>
<p>The common idioms used to accomplish this are unintuitive. This
PEP proposes two different ways of exposing the indices.</p>
</section>
<section id="loop-counter-iteration">
<h2><a class="toc-backref" href="#loop-counter-iteration" role="doc-backlink">Loop counter iteration</a></h2>
<p>The current idiom for looping over the indices makes use of the
built-in <code class="docutils literal notranslate"><span class="pre">range</span></code> function:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">)):</span>
<span class="c1"># work with index i</span>
</pre></div>
</div>
<p>Looping over both elements and indices can be achieved either by the
old idiom or by using the new <code class="docutils literal notranslate"><span class="pre">zip</span></code> built-in function <a class="footnote-reference brackets" href="#id7" id="id2">[2]</a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">)):</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">sequence</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="c1"># work with index i and element e</span>
</pre></div>
</div>
<p>or:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">)),</span> <span class="n">sequence</span><span class="p">):</span>
<span class="c1"># work with index i and element e</span>
</pre></div>
</div>
</section>
<section id="the-proposed-solutions">
<h2><a class="toc-backref" href="#the-proposed-solutions" role="doc-backlink">The Proposed Solutions</a></h2>
<p>There are three solutions that have been discussed. One adds a
non-reserved keyword, the other adds two built-in functions.
A third solution adds methods to sequence objects.</p>
</section>
<section id="non-reserved-keyword-indexing">
<h2><a class="toc-backref" href="#non-reserved-keyword-indexing" role="doc-backlink">Non-reserved keyword <code class="docutils literal notranslate"><span class="pre">indexing</span></code></a></h2>
<p>This solution would extend the syntax of the for-loop by adding
an optional <code class="docutils literal notranslate"><span class="pre">&lt;variable&gt;</span> <span class="pre">indexing</span></code> clause which can also be used
instead of the <code class="docutils literal notranslate"><span class="pre">&lt;variable&gt;</span> <span class="pre">in</span></code> clause.</p>
<p>Looping over the indices of a sequence would thus become:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="n">indexing</span> <span class="n">sequence</span><span class="p">:</span>
<span class="c1"># work with index i</span>
</pre></div>
</div>
<p>Looping over both indices and elements would similarly be:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="n">indexing</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">sequence</span><span class="p">:</span>
<span class="c1"># work with index i and element e</span>
</pre></div>
</div>
</section>
<section id="built-in-functions-indices-and-irange">
<h2><a class="toc-backref" href="#built-in-functions-indices-and-irange" role="doc-backlink">Built-in functions <code class="docutils literal notranslate"><span class="pre">indices</span></code> and <code class="docutils literal notranslate"><span class="pre">irange</span></code></a></h2>
<p>This solution adds two built-in functions <code class="docutils literal notranslate"><span class="pre">indices</span></code> and <code class="docutils literal notranslate"><span class="pre">irange</span></code>.
The semantics of these can be described as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">indices</span><span class="p">(</span><span class="n">sequence</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">irange</span><span class="p">(</span><span class="n">sequence</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">zip</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sequence</span><span class="p">)),</span> <span class="n">sequence</span><span class="p">)</span>
</pre></div>
</div>
<p>These functions could be implemented either eagerly or lazily and
should be easy to extend in order to accept more than one sequence
argument.</p>
<p>The use of these functions would simplify the idioms for looping
over the indices and over both elements and indices:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">indices</span><span class="p">(</span><span class="n">sequence</span><span class="p">):</span>
<span class="c1"># work with index i</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">irange</span><span class="p">(</span><span class="n">sequence</span><span class="p">):</span>
<span class="c1"># work with index i and element e</span>
</pre></div>
</div>
</section>
<section id="methods-for-sequence-objects">
<h2><a class="toc-backref" href="#methods-for-sequence-objects" role="doc-backlink">Methods for sequence objects</a></h2>
<p>This solution proposes the addition of <code class="docutils literal notranslate"><span class="pre">indices</span></code>, <code class="docutils literal notranslate"><span class="pre">items</span></code>
and <code class="docutils literal notranslate"><span class="pre">values</span></code> methods to sequences, which enable looping over
indices only, both indices and elements, and elements only
respectively.</p>
<p>This would immensely simplify the idioms for looping over indices
and for looping over both elements and indices:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">sequence</span><span class="o">.</span><span class="n">indices</span><span class="p">():</span>
<span class="c1"># work with index i</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">sequence</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="c1"># work with index i and element e</span>
</pre></div>
</div>
<p>Additionally it would allow to do looping over the elements
of sequences and dictionaries in a consistent way:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">sequence_or_dict</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
<span class="c1"># do something with element e</span>
</pre></div>
</div>
</section>
<section id="implementations">
<h2><a class="toc-backref" href="#implementations" role="doc-backlink">Implementations</a></h2>
<p>For all three solutions some more or less rough patches exist
as patches at SourceForge:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">i</span> <span class="pre">indexing</span> <span class="pre">a</span> <span class="pre">in</span> <span class="pre">l</span></code>: exposing the for-loop counter <a class="footnote-reference brackets" href="#id8" id="id3">[3]</a></li>
<li>add <code class="docutils literal notranslate"><span class="pre">indices()</span></code> and <code class="docutils literal notranslate"><span class="pre">irange()</span></code> to built-ins <a class="footnote-reference brackets" href="#id9" id="id4">[4]</a></li>
<li>add <code class="docutils literal notranslate"><span class="pre">items()</span></code> method to listobject <a class="footnote-reference brackets" href="#id10" id="id5">[5]</a></li>
</ul>
<p>All of them have been pronounced on and rejected by the BDFL.</p>
<p>Note that the <code class="docutils literal notranslate"><span class="pre">indexing</span></code> keyword is only a <code class="docutils literal notranslate"><span class="pre">NAME</span></code> in the
grammar and so does not hinder the general use of <code class="docutils literal notranslate"><span class="pre">indexing</span></code>.</p>
</section>
<section id="backward-compatibility-issues">
<h2><a class="toc-backref" href="#backward-compatibility-issues" role="doc-backlink">Backward Compatibility Issues</a></h2>
<p>As no keywords are added and the semantics of existing code
remains unchanged, all three solutions can be implemented
without breaking existing code.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id6" role="doc-footnote">
<dt class="label" id="id6">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://docs.python.org/reference/compound_stmts.html#for">http://docs.python.org/reference/compound_stmts.html#for</a></aside>
<aside class="footnote brackets" id="id7" role="doc-footnote">
<dt class="label" id="id7">[<a href="#id2">2</a>]</dt>
<dd>Lockstep Iteration, <a class="pep reference internal" href="../pep-0201/" title="PEP 201 Lockstep Iteration">PEP 201</a></aside>
<aside class="footnote brackets" id="id8" role="doc-footnote">
<dt class="label" id="id8">[<a href="#id3">3</a>]</dt>
<dd><a class="reference external" href="http://sourceforge.net/patch/download.php?id=101138">http://sourceforge.net/patch/download.php?id=101138</a></aside>
<aside class="footnote brackets" id="id9" role="doc-footnote">
<dt class="label" id="id9">[<a href="#id4">4</a>]</dt>
<dd><a class="reference external" href="http://sourceforge.net/patch/download.php?id=101129">http://sourceforge.net/patch/download.php?id=101129</a></aside>
<aside class="footnote brackets" id="id10" role="doc-footnote">
<dt class="label" id="id10">[<a href="#id5">5</a>]</dt>
<dd><a class="reference external" href="http://sourceforge.net/patch/download.php?id=101178">http://sourceforge.net/patch/download.php?id=101178</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0212.rst">https://github.com/python/peps/blob/main/peps/pep-0212.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0212.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#rejection-notice">Rejection Notice</a></li>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#loop-counter-iteration">Loop counter iteration</a></li>
<li><a class="reference internal" href="#the-proposed-solutions">The Proposed Solutions</a></li>
<li><a class="reference internal" href="#non-reserved-keyword-indexing">Non-reserved keyword <code class="docutils literal notranslate"><span class="pre">indexing</span></code></a></li>
<li><a class="reference internal" href="#built-in-functions-indices-and-irange">Built-in functions <code class="docutils literal notranslate"><span class="pre">indices</span></code> and <code class="docutils literal notranslate"><span class="pre">irange</span></code></a></li>
<li><a class="reference internal" href="#methods-for-sequence-objects">Methods for sequence objects</a></li>
<li><a class="reference internal" href="#implementations">Implementations</a></li>
<li><a class="reference internal" href="#backward-compatibility-issues">Backward Compatibility Issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0212.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

352
pep-0213/index.html Normal file
View File

@ -0,0 +1,352 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 213 Attribute Access Handlers | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0213/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 213 Attribute Access Handlers | peps.python.org'>
<meta property="og:description" content="It is possible (and even relatively common) in Python code and in extension modules to “trap” when an instances client code attempts to set an attribute and execute code instead. In other words, it is possible to allow users to use attribute assignment...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0213/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="It is possible (and even relatively common) in Python code and in extension modules to “trap” when an instances client code attempts to set an attribute and execute code instead. In other words, it is possible to allow users to use attribute assignment...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 213</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 213 Attribute Access Handlers</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Paul Prescod &lt;paul&#32;&#97;t&#32;prescod.net&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Inactive draft that may be taken up again at a later time">Deferred</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">21-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#justification">Justification</a><ul>
<li><a class="reference internal" href="#scenario-1">Scenario 1</a></li>
<li><a class="reference internal" href="#scenario-2">Scenario 2</a></li>
<li><a class="reference internal" href="#scenario-3">Scenario 3</a></li>
</ul>
</li>
<li><a class="reference internal" href="#current-solution">Current Solution</a></li>
<li><a class="reference internal" href="#proposed-syntax">Proposed Syntax</a></li>
<li><a class="reference internal" href="#semantics">Semantics</a></li>
<li><a class="reference internal" href="#proposed-implementation">Proposed Implementation</a></li>
<li><a class="reference internal" href="#caveats">Caveats</a></li>
<li><a class="reference internal" href="#note">Note</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>It is possible (and even relatively common) in Python code and
in extension modules to “trap” when an instances client code
attempts to set an attribute and execute code instead. In other
words, it is possible to allow users to use attribute assignment/
retrieval/deletion syntax even though the underlying implementation
is doing some computation rather than directly modifying a
binding.</p>
<p>This PEP describes a feature that makes it easier, more efficient
and safer to implement these handlers for Python instances.</p>
</section>
<section id="justification">
<h2><a class="toc-backref" href="#justification" role="doc-backlink">Justification</a></h2>
<section id="scenario-1">
<h3><a class="toc-backref" href="#scenario-1" role="doc-backlink">Scenario 1</a></h3>
<p>You have a deployed class that works on an attribute named
“stdout”. After a while, you think it would be better to
check that stdout is really an object with a “write” method
at the moment of assignment. Rather than change to a
setstdout method (which would be incompatible with deployed
code) you would rather trap the assignment and check the
objects type.</p>
</section>
<section id="scenario-2">
<h3><a class="toc-backref" href="#scenario-2" role="doc-backlink">Scenario 2</a></h3>
<p>You want to be as compatible as possible with an object
model that has a concept of attribute assignment. It could
be the W3C Document Object Model or a particular COM
interface (e.g. the PowerPoint interface). In that case
you may well want attributes in the model to show up as
attributes in the Python interface, even though the
underlying implementation may not use attributes at all.</p>
</section>
<section id="scenario-3">
<h3><a class="toc-backref" href="#scenario-3" role="doc-backlink">Scenario 3</a></h3>
<p>A user wants to make an attribute read-only.</p>
<p>In short, this feature allows programmers to separate the
interface of their module from the underlying implementation
for whatever purpose. Again, this is not a new feature but
merely a new syntax for an existing convention.</p>
</section>
</section>
<section id="current-solution">
<h2><a class="toc-backref" href="#current-solution" role="doc-backlink">Current Solution</a></h2>
<p>To make some attributes read-only:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">foo</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__setattr__</span><span class="p">(</span> <span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">val</span> <span class="p">):</span>
<span class="k">if</span> <span class="n">name</span><span class="o">==</span><span class="s2">&quot;readonlyattr&quot;</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">TypeError</span>
<span class="k">elif</span> <span class="n">name</span><span class="o">==</span><span class="s2">&quot;readonlyattr2&quot;</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">TypeError</span>
<span class="o">...</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">[</span><span class="s2">&quot;name&quot;</span><span class="p">]</span><span class="o">=</span><span class="n">val</span>
</pre></div>
</div>
<p>This has the following problems:</p>
<ol class="arabic simple">
<li>The creator of the method must be intimately aware of whether
somewhere else in the class hierarchy <code class="docutils literal notranslate"><span class="pre">__setattr__</span></code> has also been
trapped for any particular purpose. If so, she must specifically
call that method rather than assigning to the dictionary. There
are many different reasons to overload <code class="docutils literal notranslate"><span class="pre">__setattr__</span></code> so there is a
decent potential for clashes. For instance object database
implementations often overload setattr for an entirely unrelated
purpose.</li>
<li>The string-based switch statement forces all attribute handlers
to be specified in one place in the code. They may then dispatch
to task-specific methods (for modularity) but this could cause
performance problems.</li>
<li>Logic for the setting, getting and deleting must live in
<code class="docutils literal notranslate"><span class="pre">__getattr__</span></code>, <code class="docutils literal notranslate"><span class="pre">__setattr__</span></code> and <code class="docutils literal notranslate"><span class="pre">__delattr__</span></code>. Once again, this can
be mitigated through an extra level of method call but this is
inefficient.</li>
</ol>
</section>
<section id="proposed-syntax">
<h2><a class="toc-backref" href="#proposed-syntax" role="doc-backlink">Proposed Syntax</a></h2>
<p>Special methods should declare themselves with declarations of the
following form:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">x</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__attr_XXX__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">op</span><span class="p">,</span> <span class="n">val</span> <span class="p">):</span>
<span class="k">if</span> <span class="n">op</span><span class="o">==</span><span class="s2">&quot;get&quot;</span><span class="p">:</span>
<span class="k">return</span> <span class="n">someComputedValue</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">internal</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">op</span><span class="o">==</span><span class="s2">&quot;set&quot;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">internal</span><span class="o">=</span><span class="n">someComputedValue</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">op</span><span class="o">==</span><span class="s2">&quot;del&quot;</span><span class="p">:</span>
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">internal</span>
</pre></div>
</div>
<p>Client code looks like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">fooval</span><span class="o">=</span><span class="n">x</span><span class="o">.</span><span class="n">foo</span>
<span class="n">x</span><span class="o">.</span><span class="n">foo</span><span class="o">=</span><span class="n">fooval</span><span class="o">+</span><span class="mi">5</span>
<span class="k">del</span> <span class="n">x</span><span class="o">.</span><span class="n">foo</span>
</pre></div>
</div>
</section>
<section id="semantics">
<h2><a class="toc-backref" href="#semantics" role="doc-backlink">Semantics</a></h2>
<p>Attribute references of all three kinds should call the method.
The op parameter can be “get”/”set”/”del”. Of course this string
will be interned so the actual checks for the string will be
very fast.</p>
<p>It is disallowed to actually have an attribute named XXX in the
same instance as a method named __attr_XXX__.</p>
<p>An implementation of __attr_XXX__ takes precedence over an
implementation of <code class="docutils literal notranslate"><span class="pre">__getattr__</span></code> based on the principle that
<code class="docutils literal notranslate"><span class="pre">__getattr__</span></code> is supposed to be invoked only after finding an
appropriate attribute has failed.</p>
<p>An implementation of __attr_XXX__ takes precedence over an
implementation of <code class="docutils literal notranslate"><span class="pre">__setattr__</span></code> in order to be consistent. The
opposite choice seems fairly feasible also, however. The same
goes for __del_y__.</p>
</section>
<section id="proposed-implementation">
<h2><a class="toc-backref" href="#proposed-implementation" role="doc-backlink">Proposed Implementation</a></h2>
<p>There is a new object type called an attribute access handler.
Objects of this type have the following attributes:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">name</span> <span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">g</span><span class="o">.</span> <span class="n">XXX</span><span class="p">,</span> <span class="ow">not</span> <span class="n">__attr__XXX__</span><span class="p">)</span>
<span class="n">method</span> <span class="p">(</span><span class="n">pointer</span> <span class="n">to</span> <span class="n">a</span> <span class="n">method</span> <span class="nb">object</span><span class="p">)</span>
</pre></div>
</div>
<p>In PyClass_New, methods of the appropriate form will be detected and
converted into objects (just like unbound method objects). These are
stored in the class <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> under the name XXX. The original method
is stored as an unbound method under its original name.</p>
<p>If there are any attribute access handlers in an instance at all,
a flag is set. Lets call it “I_have_computed_attributes” for
now. Derived classes inherit the flag from base classes. Instances
inherit the flag from classes.</p>
<p>A get proceeds as usual until just before the object is returned.
In addition to the current check whether the returned object is a
method it would also check whether a returned object is an access
handler. If so, it would invoke the getter method and return
the value. To remove an attribute access handler you could directly
fiddle with the dictionary.</p>
<p>A set proceeds by checking the “I_have_computed_attributes” flag. If
it is not set, everything proceeds as it does today. If it is set
then we must do a dictionary get on the requested object name. If it
returns an attribute access handler then we call the setter function
with the value. If it returns any other object then we discard the
result and continue as we do today. Note that having an attribute
access handler will mildly affect attribute “setting” performance for
all sets on a particular instance, but no more so than today, using
<code class="docutils literal notranslate"><span class="pre">__setattr__</span></code>. Gets are more efficient than they are today with
<code class="docutils literal notranslate"><span class="pre">__getattr__</span></code>.</p>
<p>The I_have_computed_attributes flag is intended to eliminate the
performance degradation of an extra “get” per “set” for objects not
using this feature. Checking this flag should have minuscule
performance implications for all objects.</p>
<p>The implementation of delete is analogous to the implementation
of set.</p>
</section>
<section id="caveats">
<h2><a class="toc-backref" href="#caveats" role="doc-backlink">Caveats</a></h2>
<ol class="arabic">
<li>You might note that I have not proposed any logic to keep
the I_have_computed_attributes flag up to date as attributes
are added and removed from the instances dictionary. This is
consistent with current Python. If you add a <code class="docutils literal notranslate"><span class="pre">__setattr__</span></code> method
to an object after it is in use, that method will not behave as
it would if it were available at “compile” time. The dynamism is
arguably not worth the extra implementation effort. This snippet
demonstrates the current behavior:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">prn</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span><span class="nb">print</span> <span class="n">args</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">a</span><span class="p">:</span>
<span class="go">... __setattr__=prn</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="p">()</span><span class="o">.</span><span class="n">foo</span><span class="o">=</span><span class="mi">5</span>
<span class="go">(&lt;__main__.a instance at 882890&gt;, &#39;foo&#39;, 5)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">b</span><span class="p">:</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">bi</span><span class="o">=</span><span class="n">b</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">bi</span><span class="o">.</span><span class="fm">__setattr__</span><span class="o">=</span><span class="n">prn</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span><span class="o">.</span><span class="n">foo</span><span class="o">=</span><span class="mi">5</span>
</pre></div>
</div>
</li>
<li>Assignment to __dict__[“XXX”] can overwrite the attribute
access handler for __attr_XXX__. Typically the access handlers will
store information away in private __XXX variables</li>
<li>An attribute access handler that attempts to call setattr or getattr
on the object itself can cause an infinite loop (as with <code class="docutils literal notranslate"><span class="pre">__getattr__</span></code>)
Once again, the solution is to use a special (typically private)
variable such as __XXX.</li>
</ol>
</section>
<section id="note">
<h2><a class="toc-backref" href="#note" role="doc-backlink">Note</a></h2>
<p>The descriptor mechanism described in <a class="pep reference internal" href="../pep-0252/" title="PEP 252 Making Types Look More Like Classes">PEP 252</a> is powerful enough
to support this more directly. A getset constructor may be
added to the language making this possible:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">get_x</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__x</span>
<span class="k">def</span> <span class="nf">set_x</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">v</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__x</span> <span class="o">=</span> <span class="n">v</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">getset</span><span class="p">(</span><span class="n">get_x</span><span class="p">,</span> <span class="n">set_x</span><span class="p">)</span>
</pre></div>
</div>
<p>Additional syntactic sugar might be added, or a naming convention
could be recognized.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0213.rst">https://github.com/python/peps/blob/main/peps/pep-0213.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0213.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#justification">Justification</a><ul>
<li><a class="reference internal" href="#scenario-1">Scenario 1</a></li>
<li><a class="reference internal" href="#scenario-2">Scenario 2</a></li>
<li><a class="reference internal" href="#scenario-3">Scenario 3</a></li>
</ul>
</li>
<li><a class="reference internal" href="#current-solution">Current Solution</a></li>
<li><a class="reference internal" href="#proposed-syntax">Proposed Syntax</a></li>
<li><a class="reference internal" href="#semantics">Semantics</a></li>
<li><a class="reference internal" href="#proposed-implementation">Proposed Implementation</a></li>
<li><a class="reference internal" href="#caveats">Caveats</a></li>
<li><a class="reference internal" href="#note">Note</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0213.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

470
pep-0214/index.html Normal file
View File

@ -0,0 +1,470 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 214 Extended Print Statement | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0214/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 214 Extended Print Statement | peps.python.org'>
<meta property="og:description" content="This PEP describes a syntax to extend the standard print statement so that it can be used to print to any file-like object, instead of the default sys.stdout. This PEP tracks the status and ownership of this feature. It contains a description of the...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0214/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes a syntax to extend the standard print statement so that it can be used to print to any file-like object, instead of the default sys.stdout. This PEP tracks the status and ownership of this feature. It contains a description of the...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 214</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 214 Extended Print Statement</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">24-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.0</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">16-Aug-2000</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#justification">Justification</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#alternative-approaches">Alternative Approaches</a></li>
<li><a class="reference internal" href="#more-justification-by-the-bdfl">More Justification by the BDFL</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes a syntax to extend the standard print
statement so that it can be used to print to any file-like object,
instead of the default <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code>. This PEP tracks the status and
ownership of this feature. It contains a description of the
feature and outlines changes necessary to support the feature.
This PEP summarizes discussions held in mailing list forums, and
provides URLs for further information, where appropriate. The CVS
revision history of this file contains the definitive historical
record.</p>
</section>
<section id="proposal">
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
<p>This proposal introduces a syntax extension to the print
statement, which allows the programmer to optionally specify the
output file target. An example usage is as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">mylogfile</span><span class="p">,</span> <span class="s1">&#39;this message goes to my log file&#39;</span>
</pre></div>
</div>
<p>Formally, the syntax of the extended print statement is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">print_stmt</span><span class="p">:</span> <span class="o">...</span> <span class="o">|</span> <span class="s1">&#39;&gt;&gt;&#39;</span> <span class="n">test</span> <span class="p">[</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">test</span><span class="p">)</span><span class="o">+</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]</span> <span class="p">]</span> <span class="p">)</span>
</pre></div>
</div>
<p>where the ellipsis indicates the original print_stmt syntax
unchanged. In the extended form, the expression just after &gt;&gt;
must yield an object with a <code class="docutils literal notranslate"><span class="pre">write()</span></code> method (i.e. a file-like
object). Thus these two statements are equivalent:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="s1">&#39;hello world&#39;</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="s1">&#39;hello world&#39;</span>
</pre></div>
</div>
<p>As are these two statements:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span>
</pre></div>
</div>
<p>These two statements are syntax errors:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="p">,</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span>
</pre></div>
</div>
</section>
<section id="justification">
<h2><a class="toc-backref" href="#justification" role="doc-backlink">Justification</a></h2>
<p>print is a Python keyword and introduces the print statement as
described in section 6.6 of the language reference manual <a class="footnote-reference brackets" href="#id3" id="id1">[1]</a>.
The print statement has a number of features:</p>
<ul class="simple">
<li>it auto-converts the items to strings</li>
<li>it inserts spaces between items automatically</li>
<li>it appends a newline unless the statement ends in a comma</li>
</ul>
<p>The formatting that the print statement performs is limited; for
more control over the output, a combination of <code class="docutils literal notranslate"><span class="pre">sys.stdout.write()</span></code>,
and string interpolation can be used.</p>
<p>The print statement by definition outputs to <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code>. More
specifically, <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code> must be a file-like object with a <code class="docutils literal notranslate"><span class="pre">write()</span></code>
method, but it can be rebound to redirect output to files other
than specifically standard output. A typical idiom is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">save_stdout</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">mylogfile</span>
<span class="nb">print</span> <span class="s1">&#39;this message goes to my log file&#39;</span>
<span class="k">finally</span><span class="p">:</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">save_stdout</span>
</pre></div>
</div>
<p>The problem with this approach is that the binding is global, and
so affects every statement inside the try: clause. For example,
if we added a call to a function that actually did want to print
to stdout, this output too would get redirected to the logfile.</p>
<p>This approach is also very inconvenient for interleaving prints to
various output streams, and complicates coding in the face of
legitimate try/except or try/finally clauses.</p>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>A reference implementation, in the form of a patch against the
Python 2.0 source tree, is available on SourceForges patch
manager <a class="footnote-reference brackets" href="#id4" id="id2">[2]</a>. This approach adds two new opcodes, <code class="docutils literal notranslate"><span class="pre">PRINT_ITEM_TO</span></code> and
<code class="docutils literal notranslate"><span class="pre">PRINT_NEWLINE_TO</span></code>, which simply pop the file like object off the
top of the stack and use it instead of <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code> as the output
stream.</p>
<p>(This reference implementation has been adopted in Python 2.0.)</p>
</section>
<section id="alternative-approaches">
<h2><a class="toc-backref" href="#alternative-approaches" role="doc-backlink">Alternative Approaches</a></h2>
<p>An alternative to this syntax change has been proposed (originally
by Moshe Zadka) which requires no syntax changes to Python. A
<code class="docutils literal notranslate"><span class="pre">writeln()</span></code> function could be provided (possibly as a builtin), that
would act much like extended print, with a few additional
features:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">writeln</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kws</span><span class="p">):</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="n">file</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span>
<span class="n">sep</span> <span class="o">=</span> <span class="s1">&#39; &#39;</span>
<span class="n">end</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span>
<span class="k">if</span> <span class="n">kws</span><span class="o">.</span><span class="n">has_key</span><span class="p">(</span><span class="s1">&#39;file&#39;</span><span class="p">):</span>
<span class="n">file</span> <span class="o">=</span> <span class="n">kws</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">]</span>
<span class="k">del</span> <span class="n">kws</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">]</span>
<span class="k">if</span> <span class="n">kws</span><span class="o">.</span><span class="n">has_key</span><span class="p">(</span><span class="s1">&#39;nl&#39;</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">kws</span><span class="p">[</span><span class="s1">&#39;nl&#39;</span><span class="p">]:</span>
<span class="n">end</span> <span class="o">=</span> <span class="s1">&#39; &#39;</span>
<span class="k">del</span> <span class="n">kws</span><span class="p">[</span><span class="s1">&#39;nl&#39;</span><span class="p">]</span>
<span class="k">if</span> <span class="n">kws</span><span class="o">.</span><span class="n">has_key</span><span class="p">(</span><span class="s1">&#39;sep&#39;</span><span class="p">):</span>
<span class="n">sep</span> <span class="o">=</span> <span class="n">kws</span><span class="p">[</span><span class="s1">&#39;sep&#39;</span><span class="p">]</span>
<span class="k">del</span> <span class="n">kws</span><span class="p">[</span><span class="s1">&#39;sep&#39;</span><span class="p">]</span>
<span class="k">if</span> <span class="n">kws</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">&#39;unexpected keywords&#39;</span><span class="p">)</span>
<span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">sep</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span> <span class="o">+</span> <span class="n">end</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">writeln()</span></code> takes a three optional keyword arguments. In the
context of this proposal, the relevant argument is file which
can be set to a file-like object with a <code class="docutils literal notranslate"><span class="pre">write()</span></code> method. Thus:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">mylogfile</span><span class="p">,</span> <span class="s1">&#39;this goes to my log file&#39;</span>
</pre></div>
</div>
<p>would be written as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">writeln</span><span class="p">(</span><span class="s1">&#39;this goes to my log file&#39;</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">mylogfile</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">writeln()</span></code> has the additional functionality that the keyword
argument nl is a flag specifying whether to append a newline or
not, and an argument sep which specifies the separator to output
in between each item.</p>
</section>
<section id="more-justification-by-the-bdfl">
<h2><a class="toc-backref" href="#more-justification-by-the-bdfl" role="doc-backlink">More Justification by the BDFL</a></h2>
<p>The proposal has been challenged on the newsgroup. One series of
challenges doesnt like &gt;&gt; and would rather see some other
symbol.</p>
<ul>
<li>Challenge: Why not one of these?<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="ow">in</span> <span class="n">stderr</span> <span class="n">items</span><span class="p">,</span><span class="o">....</span>
<span class="nb">print</span> <span class="o">+</span> <span class="n">stderr</span> <span class="n">items</span><span class="p">,</span><span class="o">.......</span>
<span class="nb">print</span><span class="p">[</span><span class="n">stderr</span><span class="p">]</span> <span class="n">items</span><span class="p">,</span><span class="o">.....</span>
<span class="nb">print</span> <span class="n">to</span> <span class="n">stderr</span> <span class="n">items</span><span class="p">,</span><span class="o">.....</span>
</pre></div>
</div>
<p>Response: If we want to use a special symbol (<code class="docutils literal notranslate"><span class="pre">print</span> <span class="pre">&lt;symbol&gt;</span></code>
expression), the Python parser requires that it is not already a
symbol that can start an expression otherwise it cant decide
which form of print statement is used. (The Python parser is a
simple LL(1) or recursive descent parser.)</p>
<p>This means that we cant use the “keyword only in context trick”
that was used for “import as”, because an identifier can start an
expression. This rules out +stderr, [sterr], and to stderr. It
leaves us with binary operator symbols and other miscellaneous
symbols that are currently illegal here, such as import.</p>
<p>If I had to choose between print in file and print &gt;&gt; file I
would definitely choose &gt;&gt;. In part because in would be a new
invention (I know of no other language that uses it, while &gt;&gt; is
used in sh, awk, Perl, and C++), in part because &gt;&gt;, being
non-alphabetic, stands out more so is more likely to catch the
readers attention.</p>
</li>
<li>Challenge: Why does there have to be a comma between the file and
the rest?<p>Response: The comma separating the file from the following expression is
necessary! Of course you want the file to be an arbitrary
expression, not just a single word. (You definitely want to be
able to write <code class="docutils literal notranslate"><span class="pre">print</span> <span class="pre">&gt;&gt;sys.stderr</span></code>.) Without the expression the
parser wouldnt be able to distinguish where that expression ends
and where the next one begins, e.g.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="o">&gt;&gt;</span><span class="n">i</span> <span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span><span class="n">a</span> <span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="mi">2</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span><span class="n">f</span> <span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="mi">2</span>
</pre></div>
</div>
</li>
<li>Challenge: Why do you need a syntax extension? Why not
writeln(file, item, …)?<p>Response: First of all, this is lacking a feature of the print
statement: the trailing comma to print which suppresses the final
newline. Note that print a, still isnt equivalent to
sys.stdout.write(a) print inserts a space between items, and
takes arbitrary objects as arguments; <code class="docutils literal notranslate"><span class="pre">write()</span></code> doesnt insert a
space and requires a single string.</p>
<p>When you are considering an extension for the print statement,
its not right to add a function or method that adds a new feature
in one dimension (where the output goes) but takes away in another
dimension (spaces between items, and the choice of trailing
newline or not). We could add a whole slew of methods or
functions to deal with the various cases but that seems to add
more confusion than necessary, and would only make sense if we
were to deprecate the print statement altogether.</p>
<p>I feel that this debate is really about whether print should have
been a function or method rather than a statement. If you are in
the function camp, of course adding special syntax to the existing
print statement is not something you like. I suspect the
objection to the new syntax comes mostly from people who already
think that the print statement was a bad idea. Am I right?</p>
<p>About 10 years ago I debated with myself whether to make the most
basic from of output a function or a statement; basically I was
trying to decide between “print(item, …)” and “print item, …”.
I chose to make it a statement because printing needs to be taught
very early on, and is very important in the programs that
beginners write. Also, because ABC, which lead the way for so
many things, made it a statement. In a move thats typical for
the interaction between ABC and Python, I changed the name from
WRITE to print, and reversed the convention for adding newlines
from requiring extra syntax to add a newline (ABC used trailing
slashes to indicate newlines) to requiring extra syntax (the
trailing comma) to suppress the newline. I kept the feature that
items are separated by whitespace on output.</p>
<p>Full example: in ABC,</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">WRITE</span> <span class="mi">1</span>
<span class="n">WRITE</span> <span class="mi">2</span><span class="o">/</span>
</pre></div>
</div>
<p>has the same effect as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="mi">1</span><span class="p">,</span>
<span class="nb">print</span> <span class="mi">2</span>
</pre></div>
</div>
<p>has in Python, outputting in effect “1 2n”.</p>
<p>Im not 100% sure that the choice for a statement was right (ABC
had the compelling reason that it used statement syntax for
anything with side effects, but Python doesnt have this
convention), but Im also not convinced that its wrong. I
certainly like the economy of the print statement. (Im a rabid
Lisp-hater syntax-wise, not semantics-wise! and excessive
parentheses in syntax annoy me. Dont ever write <code class="docutils literal notranslate"><span class="pre">return(i)</span> <span class="pre">or</span>
<span class="pre">if(x==y):</span></code> in your Python code! :-)</p>
<p>Anyway, Im not ready to deprecate the print statement, and over
the years weve had many requests for an option to specify the
file.</p>
</li>
<li>Challenge: Why not &gt; instead of &gt;&gt;?<p>Response: To DOS and Unix users, &gt;&gt; suggests “append”, while &gt;
suggests “overwrite”; the semantics are closest to append. Also,
for C++ programmers, &gt;&gt; and &lt;&lt; are I/O operators.</p>
</li>
<li>Challenge: But in C++, &gt;&gt; is input and &lt;&lt; is output!<p>Response: doesnt matter; C++ clearly took it from Unix and
reversed the arrows. The important thing is that for output, the
arrow points to the file.</p>
</li>
<li>Challenge: Surely you can design a <code class="docutils literal notranslate"><span class="pre">println()</span></code> function can do all
what <code class="docutils literal notranslate"><span class="pre">print&gt;&gt;file</span></code> can do; why isnt that enough?<p>Response: I think of this in terms of a simple programming
exercise. Suppose a beginning programmer is asked to write a
function that prints the tables of multiplication. A reasonable
solution is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">tables</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="nb">print</span> <span class="n">i</span><span class="p">,</span> <span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">&#39;=&#39;</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span>
<span class="nb">print</span>
</pre></div>
</div>
<p>Now suppose the second exercise is to add printing to a different
file. With the new syntax, the programmer only needs to learn one
new thing: <code class="docutils literal notranslate"><span class="pre">print</span> <span class="pre">&gt;&gt;</span> <span class="pre">file</span></code>, and the answer can be like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">tables</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">file</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">&#39;=&#39;</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">file</span>
</pre></div>
</div>
<p>With only a print statement and a <code class="docutils literal notranslate"><span class="pre">println()</span></code> function, the
programmer first has to learn about <code class="docutils literal notranslate"><span class="pre">println()</span></code>, transforming the
original program to using <code class="docutils literal notranslate"><span class="pre">println()</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">tables</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="n">println</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">&#39;=&#39;</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span><span class="p">)</span>
<span class="n">println</span><span class="p">()</span>
</pre></div>
</div>
<p>and <strong>then</strong> about the file keyword argument:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">tables</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="n">println</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">&#39;=&#39;</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">)</span>
<span class="n">println</span><span class="p">(</span><span class="n">file</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">)</span>
</pre></div>
</div>
<p>Thus, the transformation path is longer:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="nb">print</span>
<span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">file</span>
</pre></div>
</div>
<p>vs.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="nb">print</span>
<span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="n">println</span><span class="p">()</span>
<span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="n">println</span><span class="p">(</span><span class="n">file</span><span class="o">=...</span><span class="p">)</span>
</pre></div>
</div>
<p>Note: defaulting the file argument to <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code> at compile time
is wrong, because it doesnt work right when the caller assigns to
<code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code> and then uses <code class="docutils literal notranslate"><span class="pre">tables()</span></code> without specifying the file.
This is a common problem (and would occur with a <code class="docutils literal notranslate"><span class="pre">println()</span></code>
function too). The standard solution so far has been:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">tables</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">if</span> <span class="n">file</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">file</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">file</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">&#39;=&#39;</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">file</span>
</pre></div>
</div>
<p>Ive added a feature to the implementation (which I would also
recommend to <code class="docutils literal notranslate"><span class="pre">println()</span></code>) whereby if the file argument is <code class="docutils literal notranslate"><span class="pre">None</span></code>,
<code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code> is automatically used. Thus,</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="kc">None</span><span class="p">,</span> <span class="n">foo</span> <span class="n">bar</span>
</pre></div>
</div>
<p>(or, of course, <code class="docutils literal notranslate"><span class="pre">print</span> <span class="pre">&gt;&gt;</span> <span class="pre">x</span></code> where x is a variable whose value is
None) means the same as</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="n">foo</span><span class="p">,</span> <span class="n">bar</span>
</pre></div>
</div>
<p>and the <code class="docutils literal notranslate"><span class="pre">tables()</span></code> function can be written as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">tables</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">file</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s1">&#39;=&#39;</span><span class="p">,</span> <span class="n">i</span><span class="o">*</span><span class="n">j</span>
<span class="nb">print</span> <span class="o">&gt;&gt;</span> <span class="n">file</span>
</pre></div>
</div>
</li>
</ul>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id3" role="doc-footnote">
<dt class="label" id="id3">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://docs.python.org/reference/simple_stmts.html#print">http://docs.python.org/reference/simple_stmts.html#print</a></aside>
<aside class="footnote brackets" id="id4" role="doc-footnote">
<dt class="label" id="id4">[<a href="#id2">2</a>]</dt>
<dd><a class="reference external" href="http://sourceforge.net/patch/download.php?id=100970">http://sourceforge.net/patch/download.php?id=100970</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0214.rst">https://github.com/python/peps/blob/main/peps/pep-0214.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0214.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#justification">Justification</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#alternative-approaches">Alternative Approaches</a></li>
<li><a class="reference internal" href="#more-justification-by-the-bdfl">More Justification by the BDFL</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0214.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

268
pep-0215/index.html Normal file
View File

@ -0,0 +1,268 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 215 String Interpolation | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0215/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 215 String Interpolation | peps.python.org'>
<meta property="og:description" content="This document proposes a string interpolation feature for Python to allow easier string formatting. The suggested syntax change is the introduction of a $ prefix that triggers the special interpretation of the $ character within a string, in a mann...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0215/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This document proposes a string interpolation feature for Python to allow easier string formatting. The suggested syntax change is the introduction of a $ prefix that triggers the special interpretation of the $ character within a string, in a mann...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 215</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 215 String Interpolation</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Ka-Ping Yee &lt;ping&#32;&#97;t&#32;zesty.ca&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Replaced by another succeeding PEP">Superseded</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">24-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
<dt class="field-odd">Superseded-By<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="../pep-0292/">292</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#specification">Specification</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#discussion">Discussion</a></li>
<li><a class="reference internal" href="#security-issues">Security Issues</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated superseded admonition important">
<p class="admonition-title">Important</p>
<p>This PEP has been superseded by <a class="pep reference internal" href="../pep-0292/" title="PEP 292 Simpler String Substitutions">PEP 292</a>.</p>
<p class="close-button">×</p>
<p></p>
</div>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This document proposes a string interpolation feature for Python
to allow easier string formatting. The suggested syntax change
is the introduction of a $ prefix that triggers the special
interpretation of the $ character within a string, in a manner
reminiscent to the variable interpolation found in Unix shells,
awk, Perl, or Tcl.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document is in the public domain.</p>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>Strings may be preceded with a $ prefix that comes before the
leading single or double quotation mark (or triplet) and before
any of the other string prefixes (r or u). Such a string is
processed for interpolation after the normal interpretation of
backslash-escapes in its contents. The processing occurs just
before the string is pushed onto the value stack, each time the
string is pushed. In short, Python behaves exactly as if $
were a unary operator applied to the string. The operation
performed is as follows:</p>
<p>The string is scanned from start to end for the $ character
(<code class="docutils literal notranslate"><span class="pre">\x24</span></code> in 8-bit strings or <code class="docutils literal notranslate"><span class="pre">\u0024</span></code> in Unicode strings). If there
are no $ characters present, the string is returned unchanged.</p>
<p>Any $ found in the string, followed by one of the two kinds of
expressions described below, is replaced with the value of the
expression as evaluated in the current namespaces. The value is
converted with <code class="docutils literal notranslate"><span class="pre">str()</span></code> if the containing string is an 8-bit string,
or with <code class="docutils literal notranslate"><span class="pre">unicode()</span></code> if it is a Unicode string.</p>
<ol class="arabic simple">
<li>A Python identifier optionally followed by any number of
trailers, where a trailer consists of:
- a dot and an identifier,
- an expression enclosed in square brackets, or
- an argument list enclosed in parentheses
(This is exactly the pattern expressed in the Python grammar
by “<code class="docutils literal notranslate"><span class="pre">NAME</span> <span class="pre">trailer*</span></code>”, using the definitions in <code class="docutils literal notranslate"><span class="pre">Grammar/Grammar</span></code>.)</li>
<li>Any complete Python expression enclosed in curly braces.</li>
</ol>
<p>Two dollar-signs (“$$”) are replaced with a single “$”.</p>
</section>
<section id="examples">
<h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2>
<p>Here is an example of an interactive session exhibiting the
expected behaviour of this feature.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt;&gt;&gt; a, b = 5, 6
&gt;&gt;&gt; print $&#39;a = $a, b = $b&#39;
a = 5, b = 6
&gt;&gt;&gt; $u&#39;uni${a}ode&#39;
u&#39;uni5ode&#39;
&gt;&gt;&gt; print $&#39;\$a&#39;
5
&gt;&gt;&gt; print $r&#39;\$a&#39;
\5
&gt;&gt;&gt; print $&#39;$$$a.$b&#39;
$5.6
&gt;&gt;&gt; print $&#39;a + b = ${a + b}&#39;
a + b = 11
&gt;&gt;&gt; import sys
&gt;&gt;&gt; print $&#39;References to $a: $sys.getrefcount(a)&#39;
References to 5: 15
&gt;&gt;&gt; print $&quot;sys = $sys, sys = $sys.modules[&#39;sys&#39;]&quot;
sys = &lt;module &#39;sys&#39; (built-in)&gt;, sys = &lt;module &#39;sys&#39; (built-in)&gt;
&gt;&gt;&gt; print $&#39;BDFL = $sys.copyright.split()[4].upper()&#39;
BDFL = GUIDO
</pre></div>
</div>
</section>
<section id="discussion">
<h2><a class="toc-backref" href="#discussion" role="doc-backlink">Discussion</a></h2>
<p>$ is chosen as the interpolation character within the
string for the sake of familiarity, since it is already used
for this purpose in many other languages and contexts.</p>
<p>It is then natural to choose $ as a prefix, since it is a
mnemonic for the interpolation character.</p>
<p>Trailers are permitted to give this interpolation mechanism
even more power than the interpolation available in most other
languages, while the expression to be interpolated remains
clearly visible and free of curly braces.</p>
<p>$ works like an operator and could be implemented as an
operator, but that prevents the compile-time optimization
and presents security issues. So, it is only allowed as a
string prefix.</p>
</section>
<section id="security-issues">
<h2><a class="toc-backref" href="#security-issues" role="doc-backlink">Security Issues</a></h2>
<p>“$” has the power to eval, but only to eval a literal. As
described here (a string prefix rather than an operator), it
introduces no new security issues since the expressions to be
evaluated must be literally present in the code.</p>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">Itpl</span></code> module at <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a> provides a
prototype of this feature. It uses the <code class="docutils literal notranslate"><span class="pre">tokenize</span></code> module to find
the end of an expression to be interpolated, then calls <code class="docutils literal notranslate"><span class="pre">eval()</span></code>
on the expression each time a value is needed. In the prototype,
the expression is parsed and compiled again each time it is
evaluated.</p>
<p>As an optimization, interpolated strings could be compiled
directly into the corresponding bytecode; that is,</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$&#39;a = $a, b = $b&#39;
</pre></div>
</div>
<p>could be compiled as though it were the expression</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="s1">&#39;a = &#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;, b = &#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">))</span>
</pre></div>
</div>
<p>so that it only needs to be compiled once.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://www.lfw.org/python/Itpl.py">http://www.lfw.org/python/Itpl.py</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0215.rst">https://github.com/python/peps/blob/main/peps/pep-0215.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0215.rst">2024-04-14 13:35:25 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#specification">Specification</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#discussion">Discussion</a></li>
<li><a class="reference internal" href="#security-issues">Security Issues</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0215.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

262
pep-0216/index.html Normal file
View File

@ -0,0 +1,262 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 216 Docstring Format | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0216/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 216 Docstring Format | peps.python.org'>
<meta property="og:description" content="Named Python objects, such as modules, classes and functions, have a string attribute called __doc__. If the first expression inside the definition is a literal string, that string is assigned to the __doc__ attribute.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0216/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Named Python objects, such as modules, classes and functions, have a string attribute called __doc__. If the first expression inside the definition is a literal string, that string is assigned to the __doc__ attribute.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 216</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 216 Docstring Format</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Moshe Zadka &lt;moshez&#32;&#97;t&#32;zadka.site.co.il&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">31-Jul-2000</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
<dt class="field-even">Superseded-By<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../pep-0287/">287</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#perl-documentation">Perl Documentation</a></li>
<li><a class="reference internal" href="#java-documentation">Java Documentation</a></li>
<li><a class="reference internal" href="#python-docstring-goals">Python Docstring Goals</a></li>
<li><a class="reference internal" href="#high-level-solutions">High Level Solutions</a></li>
<li><a class="reference internal" href="#docstring-format-goals">Docstring Format Goals</a></li>
<li><a class="reference internal" href="#docstring-contents">Docstring Contents</a></li>
<li><a class="reference internal" href="#docstring-basic-structure">Docstring Basic Structure</a></li>
<li><a class="reference internal" href="#unresolved-issues">Unresolved Issues</a></li>
<li><a class="reference internal" href="#rejected-suggestions">Rejected Suggestions</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated withdrawn admonition important">
<p class="admonition-title">Important</p>
<p>This PEP has been withdrawn.</p>
<p class="close-button">×</p>
<p>It has been superseded by <a class="pep reference internal" href="../pep-0287/" title="PEP 287 reStructuredText Docstring Format">PEP 287</a>.</p>
<p></p>
</div>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Named Python objects, such as modules, classes and functions, have a
string attribute called <code class="docutils literal notranslate"><span class="pre">__doc__</span></code>. If the first expression inside
the definition is a literal string, that string is assigned
to the <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> attribute.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> attribute is called a documentation string, or docstring.
It is often used to summarize the interface of the module, class or
function. However, since there is no common format for documentation
string, tools for extracting docstrings and transforming those into
documentation in a standard format (e.g., DocBook) have not sprang
up in abundance, and those that do exist are for the most part
unmaintained and unused.</p>
</section>
<section id="perl-documentation">
<h2><a class="toc-backref" href="#perl-documentation" role="doc-backlink">Perl Documentation</a></h2>
<p>In Perl, most modules are documented in a format called POD Plain
Old Documentation. This is an easy-to-type, very low level format
which integrates well with the Perl parser. Many tools exist to turn
POD documentation into other formats: info, HTML and man pages, among
others. However, in Perl, the information is not available at run-time.</p>
</section>
<section id="java-documentation">
<h2><a class="toc-backref" href="#java-documentation" role="doc-backlink">Java Documentation</a></h2>
<p>In Java, special comments before classes and functions function to
document the code. A program to extract these, and turn them into
HTML documentation is called javadoc, and is part of the standard
Java distribution. However, the only output format that is supported
is HTML, and JavaDoc has a very intimate relationship with HTML.</p>
</section>
<section id="python-docstring-goals">
<h2><a class="toc-backref" href="#python-docstring-goals" role="doc-backlink">Python Docstring Goals</a></h2>
<p>Python documentation string are easy to spot during parsing, and are
also available to the runtime interpreter. This double purpose is
a bit problematic, sometimes: for example, some are reluctant to have
too long docstrings, because they do not want to take much space in
the runtime. In addition, because of the current lack of tools, people
read objects docstrings by “print”ing them, so a tendency to make them
brief and free of markups has sprung up. This tendency hinders writing
better documentation-extraction tools, since it causes docstrings to
contain little information, which is hard to parse.</p>
</section>
<section id="high-level-solutions">
<h2><a class="toc-backref" href="#high-level-solutions" role="doc-backlink">High Level Solutions</a></h2>
<p>To counter the objection that the strings take up place in the running
program, it is suggested that documentation extraction tools will
concatenate a maximum prefix of string literals which appear in the
beginning of a definition. The first of these will also be available
in the interactive interpreter, so it should contain a few summary
lines.</p>
</section>
<section id="docstring-format-goals">
<h2><a class="toc-backref" href="#docstring-format-goals" role="doc-backlink">Docstring Format Goals</a></h2>
<p>These are the goals for the docstring format, as discussed ad nauseam
in the doc-sig.</p>
<ol class="arabic simple">
<li>It must be easy to type with any standard text editor.</li>
<li>It must be readable to the casual observer.</li>
<li>It must not contain information which can be deduced from parsing
the module.</li>
<li>It must contain sufficient information so it can be converted
to any reasonable markup format.</li>
<li>It must be possible to write a modules entire documentation in
docstrings, without feeling hampered by the markup language.</li>
</ol>
</section>
<section id="docstring-contents">
<h2><a class="toc-backref" href="#docstring-contents" role="doc-backlink">Docstring Contents</a></h2>
<p>For requirement 5. above, it is needed to specify what must be
in docstrings.</p>
<p>At least the following must be available:</p>
<ol class="loweralpha">
<li>A tag that means “this is a Python <em>something</em>, guess what”<p>Example: In the sentence “The POP3 class”, we need to markup “POP3”
so. The parser will be able to guess it is a class from the contents
of the <code class="docutils literal notranslate"><span class="pre">poplib</span></code> module, but we need to make it guess.</p>
</li>
<li>Tags that mean “this is a Python class/module/class var/instance var…”<p>Example: The usual Python idiom for singleton class <code class="docutils literal notranslate"><span class="pre">A</span></code> is to have <code class="docutils literal notranslate"><span class="pre">_A</span></code>
as the class, and <code class="docutils literal notranslate"><span class="pre">A</span></code> a function which returns <code class="docutils literal notranslate"><span class="pre">_A</span></code> objects. Its usual
to document the class, nonetheless, as being <code class="docutils literal notranslate"><span class="pre">A</span></code>. This requires the
strength to say “The class <code class="docutils literal notranslate"><span class="pre">A</span></code>” and have <code class="docutils literal notranslate"><span class="pre">A</span></code> hyperlinked and marked-up
as a class.</p>
</li>
<li>An easy way to include Python source code/Python interactive sessions</li>
<li>Emphasis/bold</li>
<li>List/tables</li>
</ol>
</section>
<section id="docstring-basic-structure">
<h2><a class="toc-backref" href="#docstring-basic-structure" role="doc-backlink">Docstring Basic Structure</a></h2>
<p>The documentation strings will be in StructuredTextNG
(<a class="reference external" href="http://www.zope.org/Members/jim/StructuredTextWiki/StructuredTextNG">http://www.zope.org/Members/jim/StructuredTextWiki/StructuredTextNG</a>)
Since StructuredText is not yet strong enough to handle (a) and (b)
above, we will need to extend it. I suggest using
<code class="docutils literal notranslate"><span class="pre">[&lt;optional</span> <span class="pre">description&gt;:python</span> <span class="pre">identifier]</span></code>.
E.g.: <code class="docutils literal notranslate"><span class="pre">[class:POP3]</span></code>, <code class="docutils literal notranslate"><span class="pre">[:POP3.list]</span></code>, etc. If the description is missing,
a guess will be made from the text.</p>
</section>
<section id="unresolved-issues">
<h2><a class="toc-backref" href="#unresolved-issues" role="doc-backlink">Unresolved Issues</a></h2>
<p>Is there a way to escape characters in ST? If so, how?
(example: * at the beginning of a line without being bullet symbol)</p>
<p>Is my suggestion above for Python symbols compatible with ST-NG?
How hard would it be to extend ST-NG to support it?</p>
<p>How do we describe input and output types of functions?</p>
<p>What additional constraint do we enforce on each docstring?
(module/class/function)?</p>
<p>What are the guesser rules?</p>
</section>
<section id="rejected-suggestions">
<h2><a class="toc-backref" href="#rejected-suggestions" role="doc-backlink">Rejected Suggestions</a></h2>
<p>XML its very hard to type, and too cluttered to read it comfortably.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0216.rst">https://github.com/python/peps/blob/main/peps/pep-0216.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0216.rst">2024-04-14 20:08:31 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#perl-documentation">Perl Documentation</a></li>
<li><a class="reference internal" href="#java-documentation">Java Documentation</a></li>
<li><a class="reference internal" href="#python-docstring-goals">Python Docstring Goals</a></li>
<li><a class="reference internal" href="#high-level-solutions">High Level Solutions</a></li>
<li><a class="reference internal" href="#docstring-format-goals">Docstring Format Goals</a></li>
<li><a class="reference internal" href="#docstring-contents">Docstring Contents</a></li>
<li><a class="reference internal" href="#docstring-basic-structure">Docstring Basic Structure</a></li>
<li><a class="reference internal" href="#unresolved-issues">Unresolved Issues</a></li>
<li><a class="reference internal" href="#rejected-suggestions">Rejected Suggestions</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0216.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

172
pep-0217/index.html Normal file
View File

@ -0,0 +1,172 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 217 Display Hook for Interactive Use | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0217/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 217 Display Hook for Interactive Use | peps.python.org'>
<meta property="og:description" content="Pythons interactive mode is one of the implementations great strengths being able to write expressions on the command line and get back a meaningful output. However, the output function cannot be all things to all people, and the current output fun...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0217/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Pythons interactive mode is one of the implementations great strengths being able to write expressions on the command line and get back a meaningful output. However, the output function cannot be all things to all people, and the current output fun...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 217</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 217 Display Hook for Interactive Use</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Moshe Zadka &lt;moshez&#32;&#97;t&#32;zadka.site.co.il&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">31-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#interface">Interface</a></li>
<li><a class="reference internal" href="#solution">Solution</a></li>
<li><a class="reference internal" href="#jython-issues">Jython Issues</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Pythons interactive mode is one of the implementations great
strengths being able to write expressions on the command line
and get back a meaningful output. However, the output function
cannot be all things to all people, and the current output
function too often falls short of this goal. This PEP describes a
way to provides alternatives to the built-in display function in
Python, so users will have control over the output from the
interactive interpreter.</p>
</section>
<section id="interface">
<h2><a class="toc-backref" href="#interface" role="doc-backlink">Interface</a></h2>
<p>The current Python solution has worked for many users, and this
should not break it. Therefore, in the default configuration,
nothing will change in the REPL loop. To change the way the
interpreter prints interactively entered expressions, users
will have to rebind <code class="docutils literal notranslate"><span class="pre">sys.displayhook</span></code> to a callable object.
The result of calling this object with the result of the
interactively entered expression should be print-able,
and this is what will be printed on <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code>.</p>
</section>
<section id="solution">
<h2><a class="toc-backref" href="#solution" role="doc-backlink">Solution</a></h2>
<p>The bytecode <code class="docutils literal notranslate"><span class="pre">PRINT_EXPR</span></code> will call <code class="docutils literal notranslate"><span class="pre">sys.displayhook(POP())</span></code>.
A <code class="docutils literal notranslate"><span class="pre">displayhook()</span></code> will be added to the sys builtin module, which is
equivalent to:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>import __builtin__
def displayhook(o):
if o is None:
return
__builtin__._ = None
print `o`
__builtin__._ = o
</pre></div>
</div>
</section>
<section id="jython-issues">
<h2><a class="toc-backref" href="#jython-issues" role="doc-backlink">Jython Issues</a></h2>
<p>The method <code class="docutils literal notranslate"><span class="pre">Py.printResult</span></code> will be similarly changed.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0217.rst">https://github.com/python/peps/blob/main/peps/pep-0217.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0217.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#interface">Interface</a></li>
<li><a class="reference internal" href="#solution">Solution</a></li>
<li><a class="reference internal" href="#jython-issues">Jython Issues</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0217.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

347
pep-0218/index.html Normal file
View File

@ -0,0 +1,347 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 218 Adding a Built-In Set Object Type | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0218/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 218 Adding a Built-In Set Object Type | peps.python.org'>
<meta property="og:description" content="This PEP proposes adding a Set module to the standard Python library, and to then make sets a built-in Python type if that module is widely used. After explaining why sets are desirable, and why the common idiom of using dictionaries in their place is ...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0218/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP proposes adding a Set module to the standard Python library, and to then make sets a built-in Python type if that module is widely used. After explaining why sets are desirable, and why the common idiom of using dictionaries in their place is ...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 218</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 218 Adding a Built-In Set Object Type</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Greg Wilson &lt;gvwilson&#32;&#97;t&#32;ddj.com&gt;, Raymond Hettinger &lt;python&#32;&#97;t&#32;rcn.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">31-Jul-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.2</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#set-notation">Set Notation</a></li>
<li><a class="reference internal" href="#history">History</a></li>
<li><a class="reference internal" href="#mutability">Mutability</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP proposes adding a Set module to the standard Python
library, and to then make sets a built-in Python type if that
module is widely used. After explaining why sets are desirable,
and why the common idiom of using dictionaries in their place is
inadequate, we describe how we intend built-in sets to work, and
then how the preliminary Set module will behave. The last
section discusses the mutability (or otherwise) of sets and set
elements, and the solution which the Set module will implement.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>Sets are a fundamental mathematical structure, and are very
commonly used in algorithm specifications. They are much less
frequently used in implementations, even when they are the “right”
structure. Programmers frequently use lists instead, even when
the ordering information in lists is irrelevant, and by-value
lookups are frequent. (Most medium-sized C programs contain a
depressing number of start-to-end searches through mallocd
vectors to determine whether particular items are present or
not…)</p>
<p>Programmers are often told that they can implement sets as
dictionaries with “dont care” values. Items can be added to
these “sets” by assigning the “dont care” value to them;
membership can be tested using <code class="docutils literal notranslate"><span class="pre">dict.has_key</span></code>; and items can be
deleted using <code class="docutils literal notranslate"><span class="pre">del</span></code>. However, the other main operations on sets
(union, intersection, and difference) are not directly supported
by this representation, since their meaning is ambiguous for
dictionaries containing key/value pairs.</p>
</section>
<section id="proposal">
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
<p>The long-term goal of this PEP is to add a built-in set type to
Python. This type will be an unordered collection of unique
values, just as a dictionary is an unordered collection of
key/value pairs.</p>
<p>Iteration and comprehension will be implemented in the obvious
ways, so that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">S</span><span class="p">:</span>
</pre></div>
</div>
<p>will step through the elements of S in arbitrary order, while:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">set</span><span class="p">(</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">S</span><span class="p">)</span>
</pre></div>
</div>
<p>will produce a set containing the squares of all elements in S,
Membership will be tested using <code class="docutils literal notranslate"><span class="pre">in</span></code> and <code class="docutils literal notranslate"><span class="pre">not</span> <span class="pre">in</span></code>, and basic set
operations will be implemented by a mixture of overloaded
operators:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">|</span></code></td>
<td>union</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">&amp;</span></code></td>
<td>intersection</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">^</span></code></td>
<td>symmetric difference</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">-</span></code></td>
<td>asymmetric difference</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">==</span> <span class="pre">!=</span></code></td>
<td>equality and inequality tests</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">&lt;</span> <span class="pre">&lt;=</span> <span class="pre">&gt;=</span> <span class="pre">&gt;</span></code></td>
<td>subset and superset tests</td>
</tr>
</tbody>
</table>
<p>and methods:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">S.add(x)</span></code></td>
<td>Add “x” to the set.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">S.update(s)</span></code></td>
<td>Add all elements of sequence “s” to the set.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">S.remove(x)</span></code></td>
<td>Remove “x” from the set. If “x” is not
present, this method raises a <code class="docutils literal notranslate"><span class="pre">LookupError</span></code>
exception.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">S.discard(x)</span></code></td>
<td>Remove “x” from the set if it is present, or
do nothing if it is not.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">S.pop()</span></code></td>
<td>Remove and return an arbitrary element,
raising a <code class="docutils literal notranslate"><span class="pre">LookupError</span></code> if the element is
not present.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">S.clear()</span></code></td>
<td>Remove all elements from this set.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">S.copy()</span></code></td>
<td>Make a new set.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">s.issuperset()</span></code></td>
<td>Check for a superset relationship.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">s.issubset()</span></code></td>
<td>Check for a subset relationship.</td>
</tr>
</tbody>
</table>
<p>and two new built-in conversion functions:</p>
<table class="docutils align-default">
<tbody>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">set(x)</span></code></td>
<td>Create a set containing the elements of the
collection “x”.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">frozenset(x)</span></code></td>
<td>Create an immutable set containing the elements
of the collection “x”.</td>
</tr>
</tbody>
</table>
<p>Notes:</p>
<ol class="arabic simple">
<li>We propose using the bitwise operators “<code class="docutils literal notranslate"><span class="pre">|&amp;</span></code>” for intersection
and union. While “<code class="docutils literal notranslate"><span class="pre">+</span></code>” for union would be intuitive, “<code class="docutils literal notranslate"><span class="pre">*</span></code>” for
intersection is not (very few of the people asked guessed what
it did correctly).</li>
<li>We considered using “<code class="docutils literal notranslate"><span class="pre">+</span></code>” to add elements to a set, rather than
“add”. However, Guido van Rossum pointed out that “<code class="docutils literal notranslate"><span class="pre">+</span></code>” is
symmetric for other built-in types (although “<code class="docutils literal notranslate"><span class="pre">*</span></code>” is not). Use
of “add” will also avoid confusion between that operation and
set union.</li>
</ol>
</section>
<section id="set-notation">
<h2><a class="toc-backref" href="#set-notation" role="doc-backlink">Set Notation</a></h2>
<p>The PEP originally proposed <code class="docutils literal notranslate"><span class="pre">{1,2,3}</span></code> as the set notation and <code class="docutils literal notranslate"><span class="pre">{-}</span></code> for
the empty set. Experience with Python 2.3s <code class="docutils literal notranslate"><span class="pre">sets.py</span></code> showed that
the notation was not necessary. Also, there was some risk of making
dictionaries less instantly recognizable.</p>
<p>It was also contemplated that the braced notation would support set
comprehensions; however, Python 2.4 provided generator expressions
which fully met that need and did so it a more general way.
(See <a class="pep reference internal" href="../pep-0289/" title="PEP 289 Generator Expressions">PEP 289</a> for details on generator expressions).</p>
<p>So, Guido ruled that there would not be a set syntax; however, the
issue could be revisited for Python 3000 (see <a class="pep reference internal" href="../pep-3000/" title="PEP 3000 Python 3000">PEP 3000</a>).</p>
</section>
<section id="history">
<h2><a class="toc-backref" href="#history" role="doc-backlink">History</a></h2>
<p>To gain experience with sets, a pure python module was introduced
in Python 2.3. Based on that implementation, the set and frozenset
types were introduced in Python 2.4. The improvements are:</p>
<ul class="simple">
<li>Better hash algorithm for frozensets</li>
<li>More compact pickle format (storing only an element list
instead of a dictionary of key:value pairs where the value
is always <code class="docutils literal notranslate"><span class="pre">True</span></code>).</li>
<li>Use a <code class="docutils literal notranslate"><span class="pre">__reduce__</span></code> function so that deep copying is automatic.</li>
<li>The BaseSet concept was eliminated.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">union_update()</span></code> method became just <code class="docutils literal notranslate"><span class="pre">update()</span></code>.</li>
<li>Auto-conversion between mutable and immutable sets was dropped.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">_repr</span></code> method was dropped (the need is met by the new
<code class="docutils literal notranslate"><span class="pre">sorted()</span></code> built-in function).</li>
</ul>
<p>Tim Peters believes that the classs constructor should take a
single sequence as an argument, and populate the set with that
sequences elements. His argument is that in most cases,
programmers will be creating sets from pre-existing sequences, so
that this case should be the common one. However, this would
require users to remember an extra set of parentheses when
initializing a set with known values:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">Set</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span> <span class="c1"># case 1</span>
</pre></div>
</div>
<p>On the other hand, feedback from a small number of novice Python
users (all of whom were very experienced with other languages)
indicates that people will find a “parenthesis-free” syntax more
natural:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">Set</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span> <span class="c1"># case 2</span>
</pre></div>
</div>
<p>Ultimately, we adopted the first strategy in which the initializer
takes a single iterable argument.</p>
</section>
<section id="mutability">
<h2><a class="toc-backref" href="#mutability" role="doc-backlink">Mutability</a></h2>
<p>The most difficult question to resolve in this proposal was
whether sets ought to be able to contain mutable elements. A
dictionarys keys must be immutable in order to support fast,
reliable lookup. While it would be easy to require set elements
to be immutable, this would preclude sets of sets (which are
widely used in graph algorithms and other applications).</p>
<p>Earlier drafts of <a class="pep reference internal" href="../pep-0218/" title="PEP 218 Adding a Built-In Set Object Type">PEP 218</a> had only a single set type, but the
<code class="docutils literal notranslate"><span class="pre">sets.py</span></code> implementation in Python 2.3 has two, Set and
ImmutableSet. For Python 2.4, the new built-in types were named
<code class="docutils literal notranslate"><span class="pre">set</span></code> and <code class="docutils literal notranslate"><span class="pre">frozenset</span></code> which are slightly less cumbersome.</p>
<p>There are two classes implemented in the “sets” module. Instances
of the Set class can be modified by the addition or removal of
elements, and the ImmutableSet class is “frozen”, with an
unchangeable collection of elements. Therefore, an ImmutableSet
may be used as a dictionary key or as a set element, but cannot be
updated. Both types of set require that their elements are
immutable, hashable objects. Parallel comments apply to the “set”
and “frozenset” built-in types.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the Public Domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0218.rst">https://github.com/python/peps/blob/main/peps/pep-0218.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0218.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#set-notation">Set Notation</a></li>
<li><a class="reference internal" href="#history">History</a></li>
<li><a class="reference internal" href="#mutability">Mutability</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0218.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

294
pep-0219/index.html Normal file
View File

@ -0,0 +1,294 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 219 Stackless Python | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0219/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 219 Stackless Python | peps.python.org'>
<meta property="og:description" content="This PEP discusses changes required to core Python in order to efficiently support generators, microthreads and coroutines. It is related to PEP 220, which describes how Python should be extended to support these facilities. The focus of this PEP is str...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0219/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP discusses changes required to core Python in order to efficiently support generators, microthreads and coroutines. It is related to PEP 220, which describes how Python should be extended to support these facilities. The focus of this PEP is str...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 219</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 219 Stackless Python</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Gordon McMillan &lt;gmcm&#32;&#97;t&#32;hypernet.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Inactive draft that may be taken up again at a later time">Deferred</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">14-Aug-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#discussion">Discussion</a></li>
<li><a class="reference internal" href="#problems">Problems</a></li>
<li><a class="reference internal" href="#advantages">Advantages</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP discusses changes required to core Python in order to
efficiently support generators, microthreads and coroutines. It is
related to <a class="pep reference internal" href="../pep-0220/" title="PEP 220 Coroutines, Generators, Continuations">PEP 220</a>, which describes how Python should be extended
to support these facilities. The focus of this PEP is strictly on
the changes required to allow these extensions to work.</p>
<p>While these PEPs are based on Christian Tismers Stackless <a class="footnote-reference brackets" href="#id5" id="id1">[1]</a>
implementation, they do not regard Stackless as a reference
implementation. Stackless (with an extension module) implements
continuations, and from continuations one can implement
coroutines, microthreads (as has been done by Will Ware <a class="footnote-reference brackets" href="#id6" id="id2">[2]</a>) and
generators. But in more than a year, no one has found any other
productive use of continuations, so there seems to be no demand
for their support.</p>
<p>However, Stackless support for continuations is a relatively minor
piece of the implementation, so one might regard it as “a”
reference implementation (rather than “the” reference
implementation).</p>
</section>
<section id="background">
<h2><a class="toc-backref" href="#background" role="doc-backlink">Background</a></h2>
<p>Generators and coroutines have been implemented in a number of
languages in a number of ways. Indeed, Tim Peters has done pure
Python implementations of generators <a class="footnote-reference brackets" href="#id7" id="id3">[3]</a> and coroutines <a class="footnote-reference brackets" href="#id8" id="id4">[4]</a> using
threads (and a thread-based coroutine implementation exists for
Java). However, the horrendous overhead of a thread-based
implementation severely limits the usefulness of this approach.</p>
<p>Microthreads (a.k.a “green” or “user” threads) and coroutines
involve transfers of control that are difficult to accommodate in
a language implementation based on a single stack. (Generators can
be done on a single stack, but they can also be regarded as a very
simple case of coroutines.)</p>
<p>Real threads allocate a full-sized stack for each thread of
control, and this is the major source of overhead. However,
coroutines and microthreads can be implemented in Python in a way
that involves almost no overhead. This PEP, therefore, offers a
way for making Python able to realistically manage thousands of
separate “threads” of activity (vs. todays limit of perhaps dozens
of separate threads of activity).</p>
<p>Another justification for this PEP (explored in <a class="pep reference internal" href="../pep-0220/" title="PEP 220 Coroutines, Generators, Continuations">PEP 220</a>) is that
coroutines and generators often allow a more direct expression of
an algorithm than is possible in todays Python.</p>
</section>
<section id="discussion">
<h2><a class="toc-backref" href="#discussion" role="doc-backlink">Discussion</a></h2>
<p>The first thing to note is that Python, while it mingles
interpreter data (normal C stack usage) with Python data (the
state of the interpreted program) on the stack, the two are
logically separate. They just happen to use the same stack.</p>
<p>A real thread gets something approaching a process-sized stack
because the implementation has no way of knowing how much stack
space the thread will require. The stack space required for an
individual frame is likely to be reasonable, but stack switching
is an arcane and non-portable process, not supported by C.</p>
<p>Once Python stops putting Python data on the C stack, however,
stack switching becomes easy.</p>
<p>The fundamental approach of the PEP is based on these two
ideas. First, separate Cs stack usage from Pythons stack
usage. Secondly, associate with each frame enough stack space to
handle that frames execution.</p>
<p>In the normal usage, Stackless Python has a normal stack
structure, except that it is broken into chunks. But in the
presence of a coroutine / microthread extension, this same
mechanism supports a stack with a tree structure. That is, an
extension can support transfers of control between frames outside
the normal “call / return” path.</p>
</section>
<section id="problems">
<h2><a class="toc-backref" href="#problems" role="doc-backlink">Problems</a></h2>
<p>The major difficulty with this approach is C calling Python. The
problem is that the C stack now holds a nested execution of the
byte-code interpreter. In that situation, a coroutine /
microthread extension cannot be permitted to transfer control to a
frame in a different invocation of the byte-code interpreter. If a
frame were to complete and exit back to C from the wrong
interpreter, the C stack could be trashed.</p>
<p>The ideal solution is to create a mechanism where nested
executions of the byte code interpreter are never needed. The easy
solution is for the coroutine / microthread extension(s) to
recognize the situation and refuse to allow transfers outside the
current invocation.</p>
<p>We can categorize code that involves C calling Python into two
camps: Pythons implementation, and C extensions. And hopefully we
can offer a compromise: Pythons internal usage (and C extension
writers who want to go to the effort) will no longer use a nested
invocation of the interpreter. Extensions which do not go to the
effort will still be safe, but will not play well with coroutines
/ microthreads.</p>
<p>Generally, when a recursive call is transformed into a loop, a bit
of extra bookkeeping is required. The loop will need to keep its
own “stack” of arguments and results since the real stack can now
only hold the most recent. The code will be more verbose, because
its not quite as obvious when were done. While Stackless is not
implemented this way, it has to deal with the same issues.</p>
<p>In normal Python, <code class="docutils literal notranslate"><span class="pre">PyEval_EvalCode</span></code> is used to build a frame and
execute it. Stackless Python introduces the concept of a
<code class="docutils literal notranslate"><span class="pre">FrameDispatcher</span></code>. Like <code class="docutils literal notranslate"><span class="pre">PyEval_EvalCode</span></code>, it executes one frame. But
the interpreter may signal the <code class="docutils literal notranslate"><span class="pre">FrameDispatcher</span></code> that a new frame
has been swapped in, and the new frame should be executed. When a
frame completes, the <code class="docutils literal notranslate"><span class="pre">FrameDispatcher</span></code> follows the back pointer to
resume the “calling” frame.</p>
<p>So Stackless transforms recursions into a loop, but it is not the
<code class="docutils literal notranslate"><span class="pre">FrameDispatcher</span></code> that manages the frames. This is done by the
interpreter (or an extension that knows what its doing).</p>
<p>The general idea is that where C code needs to execute Python
code, it creates a frame for the Python code, setting its back
pointer to the current frame. Then it swaps in the frame, signals
the <code class="docutils literal notranslate"><span class="pre">FrameDispatcher</span></code> and gets out of the way. The C stack is now
clean - the Python code can transfer control to any other frame
(if an extension gives it the means to do so).</p>
<p>In the vanilla case, this magic can be hidden from the programmer
(even, in most cases, from the Python-internals programmer). Many
situations present another level of difficulty, however.</p>
<p>The map builtin function involves two obstacles to this
approach. It cannot simply construct a frame and get out of the
way, not just because theres a loop involved, but each pass
through the loop requires some “post” processing. In order to play
well with others, Stackless constructs a frame object for map
itself.</p>
<p>Most recursions of the interpreter are not this complex, but
fairly frequently, some “post” operations are required. Stackless
does not fix these situations because of the amount of code changes
required. Instead, Stackless prohibits transfers out of a nested
interpreter. While not ideal (and sometimes puzzling), this
limitation is hardly crippling.</p>
</section>
<section id="advantages">
<h2><a class="toc-backref" href="#advantages" role="doc-backlink">Advantages</a></h2>
<p>For normal Python, the advantage to this approach is that C stack
usage becomes much smaller and more predictable. Unbounded
recursion in Python code becomes a memory error, instead of a
stack error (and thus, in non-Cupertino operating systems,
something that can be recovered from). The price, of course, is
the added complexity that comes from transforming recursions of
the byte-code interpreter loop into a higher order loop (and the
attendant bookkeeping involved).</p>
<p>The big advantage comes from realizing that the Python stack is
really a tree, and the frame dispatcher can transfer control
freely between leaf nodes of the tree, thus allowing things like
microthreads and coroutines.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id5" role="doc-footnote">
<dt class="label" id="id5">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://www.stackless.com">http://www.stackless.com</a></aside>
<aside class="footnote brackets" id="id6" role="doc-footnote">
<dt class="label" id="id6">[<a href="#id2">2</a>]</dt>
<dd><a class="reference external" href="http://web.archive.org/web/20000815070602/http://world.std.com/~wware/uthread.html">http://web.archive.org/web/20000815070602/http://world.std.com/~wware/uthread.html</a></aside>
<aside class="footnote brackets" id="id7" role="doc-footnote">
<dt class="label" id="id7">[<a href="#id3">3</a>]</dt>
<dd>Demo/threads/Generator.py in the source distribution</aside>
<aside class="footnote brackets" id="id8" role="doc-footnote">
<dt class="label" id="id8">[<a href="#id4">4</a>]</dt>
<dd><a class="reference external" href="http://www.stackless.com/coroutines.tim.peters.html">http://www.stackless.com/coroutines.tim.peters.html</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0219.rst">https://github.com/python/peps/blob/main/peps/pep-0219.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0219.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#discussion">Discussion</a></li>
<li><a class="reference internal" href="#problems">Problems</a></li>
<li><a class="reference internal" href="#advantages">Advantages</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0219.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

139
pep-0220/index.html Normal file
View File

@ -0,0 +1,139 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 220 Coroutines, Generators, Continuations | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0220/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 220 Coroutines, Generators, Continuations | peps.python.org'>
<meta property="og:description" content="Demonstrates why the changes described in the stackless PEP are desirable. A low-level continuations module exists. With it, coroutines and generators and “green” threads can be written. A higher level module that makes coroutines and generators easy...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0220/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Demonstrates why the changes described in the stackless PEP are desirable. A low-level continuations module exists. With it, coroutines and generators and “green” threads can be written. A higher level module that makes coroutines and generators easy...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 220</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 220 Coroutines, Generators, Continuations</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Gordon McMillan &lt;gmcm&#32;&#97;t&#32;hypernet.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">14-Aug-2000</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated rejected admonition warning">
<p class="admonition-title">Warning</p>
<p>This PEP has been rejected.</p>
<p class="close-button">×</p>
<p></p>
</div>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Demonstrates why the changes described in the stackless PEP are
desirable. A low-level continuations module exists. With it,
coroutines and generators and “green” threads can be written. A
higher level module that makes coroutines and generators easy to
create is desirable (and being worked on). The focus of this PEP
is on showing how coroutines, generators, and green threads can
simplify common programming problems.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0220.rst">https://github.com/python/peps/blob/main/peps/pep-0220.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0220.rst">2024-04-14 13:35:25 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0220.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

231
pep-0221/index.html Normal file
View File

@ -0,0 +1,231 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 221 Import As | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0221/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 221 Import As | peps.python.org'>
<meta property="og:description" content="This PEP describes the import as proposal for Python 2.0. This PEP tracks the status and ownership of this feature. It contains a description of the feature and outlines changes necessary to support the feature. The CVS revision history of this file ...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0221/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the import as proposal for Python 2.0. This PEP tracks the status and ownership of this feature. It contains a description of the feature and outlines changes necessary to support the feature. The CVS revision history of this file ...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 221</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 221 Import As</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Thomas Wouters &lt;thomas&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">15-Aug-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.0</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#implementation-details">Implementation details</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes the <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">as</span></code> proposal for Python 2.0. This
PEP tracks the status and ownership of this feature. It contains
a description of the feature and outlines changes necessary to
support the feature. The CVS revision history of this file
contains the definitive historical record.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>This PEP proposes an extension of Python syntax regarding the
<code class="docutils literal notranslate"><span class="pre">import</span></code> and <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">&lt;module&gt;</span> <span class="pre">import</span></code> statements. These statements
load in a module, and either bind that module to a local name, or
binds objects from that module to a local name. However, it is
sometimes desirable to bind those objects to a different name, for
instance to avoid name clashes. This can currently be achieved
using the following idiom:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>
<span class="n">real_os</span> <span class="o">=</span> <span class="n">os</span>
<span class="k">del</span> <span class="n">os</span>
</pre></div>
</div>
<p>And similarly for the <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">...</span> <span class="pre">import</span></code> statement:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">os</span> <span class="kn">import</span> <span class="n">fdopen</span><span class="p">,</span> <span class="n">exit</span><span class="p">,</span> <span class="n">stat</span>
<span class="n">os_fdopen</span> <span class="o">=</span> <span class="n">fdopen</span>
<span class="n">os_stat</span> <span class="o">=</span> <span class="n">stat</span>
<span class="k">del</span> <span class="n">fdopen</span><span class="p">,</span> <span class="n">stat</span>
</pre></div>
</div>
<p>The proposed syntax change would add an optional <code class="docutils literal notranslate"><span class="pre">as</span></code> clause to
both these statements, as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span> <span class="k">as</span> <span class="nn">real_os</span>
<span class="kn">from</span> <span class="nn">os</span> <span class="kn">import</span> <span class="n">fdopen</span> <span class="k">as</span> <span class="n">os_fdopen</span><span class="p">,</span> <span class="n">exit</span><span class="p">,</span> <span class="n">stat</span> <span class="k">as</span> <span class="n">os_stat</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">as</span></code> name is not intended to be a keyword, and some trickery
has to be used to convince the CPython parser it isnt one. For
more advanced parsers/tokenizers, however, this should not be a
problem.</p>
<p>A slightly special case exists for importing sub-modules. The
statement</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os.path</span>
</pre></div>
</div>
<p>stores the module <code class="docutils literal notranslate"><span class="pre">os</span></code> locally as <code class="docutils literal notranslate"><span class="pre">os</span></code>, so that the imported
submodule <code class="docutils literal notranslate"><span class="pre">path</span></code> is accessible as <code class="docutils literal notranslate"><span class="pre">os.path</span></code>. As a result,</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os.path</span> <span class="k">as</span> <span class="nn">p</span>
</pre></div>
</div>
<p>stores <code class="docutils literal notranslate"><span class="pre">os.path</span></code>, not <code class="docutils literal notranslate"><span class="pre">os</span></code>, in <code class="docutils literal notranslate"><span class="pre">p</span></code>. This makes it effectively the
same as</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">os</span> <span class="kn">import</span> <span class="n">path</span> <span class="k">as</span> <span class="n">p</span>
</pre></div>
</div>
</section>
<section id="implementation-details">
<h2><a class="toc-backref" href="#implementation-details" role="doc-backlink">Implementation details</a></h2>
<p>This PEP has been accepted, and the suggested code change has been
checked in. The patch can still be found in the SourceForge patch
manager <a class="footnote-reference brackets" href="#id3" id="id1">[1]</a>. Currently, a <code class="docutils literal notranslate"><span class="pre">NAME</span></code> field is used in the grammar rather
than a bare string, to avoid the keyword issue. It introduces a
new bytecode, <code class="docutils literal notranslate"><span class="pre">IMPORT_STAR</span></code>, which performs the <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">module</span> <span class="pre">import</span>
<span class="pre">*</span></code> behaviour, and changes the behaviour of the <code class="docutils literal notranslate"><span class="pre">IMPORT_FROM</span></code>
bytecode so that it loads the requested name (which is always a
single name) onto the stack, to be subsequently stored by a <code class="docutils literal notranslate"><span class="pre">STORE</span></code>
opcode. As a result, all names explicitly imported now follow the
<code class="docutils literal notranslate"><span class="pre">global</span></code> directives.</p>
<p>The special case of <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">module</span> <span class="pre">import</span> <span class="pre">*</span></code> remains a special case,
in that it cannot accommodate an <code class="docutils literal notranslate"><span class="pre">as</span></code> clause, and that no <code class="docutils literal notranslate"><span class="pre">STORE</span></code>
opcodes are generated; the objects imported are loaded directly
into the local namespace. This also means that names imported in
this fashion are always local, and do not follow the <code class="docutils literal notranslate"><span class="pre">global</span></code>
directive.</p>
<p>An additional change to this syntax has also been suggested, to
generalize the expression given after the <code class="docutils literal notranslate"><span class="pre">as</span></code> clause. Rather
than a single name, it could be allowed to be any expression that
yields a valid l-value; anything that can be assigned to. The
change to accommodate this is minimal, as the patch <a class="footnote-reference brackets" href="#id4" id="id2">[2]</a> proves, and
the resulting generalization allows a number of new constructs
that run completely parallel with other Python assignment
constructs. However, this idea has been rejected by Guido, as
“hypergeneralization”.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the Public Domain.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id3" role="doc-footnote">
<dt class="label" id="id3">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="https://hg.python.org/cpython/rev/18385172fac0">https://hg.python.org/cpython/rev/18385172fac0</a></aside>
<aside class="footnote brackets" id="id4" role="doc-footnote">
<dt class="label" id="id4">[<a href="#id2">2</a>]</dt>
<dd><a class="reference external" href="http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=101234&amp;group_id=5470">http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=101234&amp;group_id=5470</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0221.rst">https://github.com/python/peps/blob/main/peps/pep-0221.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0221.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#implementation-details">Implementation details</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0221.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

367
pep-0222/index.html Normal file
View File

@ -0,0 +1,367 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 222 Web Library Enhancements | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0222/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 222 Web Library Enhancements | peps.python.org'>
<meta property="og:description" content="This PEP proposes a set of enhancements to the CGI development facilities in the Python standard library. Enhancements might be new features, new modules for tasks such as cookie support, or removal of obsolete code.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0222/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP proposes a set of enhancements to the CGI development facilities in the Python standard library. Enhancements might be new features, new modules for tasks such as cookie support, or removal of obsolete code.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 222</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 222 Web Library Enhancements</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">A.M. Kuchling &lt;amk&#32;&#97;t&#32;amk.ca&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Inactive draft that may be taken up again at a later time">Deferred</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">18-Aug-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">22-Dec-2000</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#new-modules">New Modules</a></li>
<li><a class="reference internal" href="#major-changes-to-existing-modules">Major Changes to Existing Modules</a></li>
<li><a class="reference internal" href="#minor-changes-to-existing-modules">Minor Changes to Existing Modules</a></li>
<li><a class="reference internal" href="#rejected-changes">Rejected Changes</a></li>
<li><a class="reference internal" href="#proposed-interface">Proposed Interface</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP proposes a set of enhancements to the CGI development
facilities in the Python standard library. Enhancements might be
new features, new modules for tasks such as cookie support, or
removal of obsolete code.</p>
<p>The original intent was to make improvements to Python 2.1.
However, there seemed little interest from the Python community,
and time was lacking, so this PEP has been deferred to some future
Python release.</p>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
<p>This section lists changes that have been suggested, but about
which no firm decision has yet been made. In the final version of
this PEP, this section should be empty, as all the changes should
be classified as accepted or rejected.</p>
<p>cgi.py: We should not be told to create our own subclass just so
we can handle file uploads. As a practical matter, I have yet to
find the time to do this right, so I end up reading cgi.pys temp
file into, at best, another file. Some of our legacy code actually
reads it into a second temp file, then into a final destination!
And even if we did, that would mean creating yet another object
with its <code class="docutils literal notranslate"><span class="pre">__init__</span></code> call and associated overhead.</p>
<p>cgi.py: Currently, query data with no <code class="docutils literal notranslate"><span class="pre">=</span></code> are ignored. Even if
<code class="docutils literal notranslate"><span class="pre">keep_blank_values</span></code> is set, queries like <code class="docutils literal notranslate"><span class="pre">...?value=&amp;...</span></code> are
returned with blank values but queries like <code class="docutils literal notranslate"><span class="pre">...?value&amp;...</span></code> are
completely lost. It would be great if such data were made
available through the <code class="docutils literal notranslate"><span class="pre">FieldStorage</span></code> interface, either as entries
with <code class="docutils literal notranslate"><span class="pre">None</span></code> as values, or in a separate list.</p>
<p>Utility function: build a query string from a list of 2-tuples</p>
<p>Dictionary-related utility classes: <code class="docutils literal notranslate"><span class="pre">NoKeyErrors</span></code> (returns an empty
string, never a <code class="docutils literal notranslate"><span class="pre">KeyError</span></code>), <code class="docutils literal notranslate"><span class="pre">PartialStringSubstitution</span></code> (returns
the original key string, never a <code class="docutils literal notranslate"><span class="pre">KeyError</span></code>)</p>
</section>
<section id="new-modules">
<h2><a class="toc-backref" href="#new-modules" role="doc-backlink">New Modules</a></h2>
<p>This section lists details about entire new packages or modules
that should be added to the Python standard library.</p>
<ul class="simple">
<li>fcgi.py : A new module adding support for the FastCGI protocol.
Robin Dunns code needs to be ported to Windows, though.</li>
</ul>
</section>
<section id="major-changes-to-existing-modules">
<h2><a class="toc-backref" href="#major-changes-to-existing-modules" role="doc-backlink">Major Changes to Existing Modules</a></h2>
<p>This section lists details of major changes to existing modules,
whether in implementation or in interface. The changes in this
section therefore carry greater degrees of risk, either in
introducing bugs or a backward incompatibility.</p>
<p>The cgi.py module would be deprecated. (XXX A new module or
package name hasnt been chosen yet: web? cgilib?)</p>
</section>
<section id="minor-changes-to-existing-modules">
<h2><a class="toc-backref" href="#minor-changes-to-existing-modules" role="doc-backlink">Minor Changes to Existing Modules</a></h2>
<p>This section lists details of minor changes to existing modules.
These changes should have relatively small implementations, and
have little risk of introducing incompatibilities with previous
versions.</p>
</section>
<section id="rejected-changes">
<h2><a class="toc-backref" href="#rejected-changes" role="doc-backlink">Rejected Changes</a></h2>
<p>The changes listed in this section were proposed for Python 2.1,
but were rejected as unsuitable. For each rejected change, a
rationale is given describing why the change was deemed
inappropriate.</p>
<ul class="simple">
<li>An HTML generation module is not part of this PEP. Several such
modules exist, ranging from HTMLgens purely programming
interface to ASP-inspired simple templating to DTMLs complex
templating. Theres no indication of which templating module to
enshrine in the standard library, and that probably means that
no module should be so chosen.</li>
<li>cgi.py: Allowing a combination of query data and POST data.
This doesnt seem to be standard at all, and therefore is
dubious practice.</li>
</ul>
</section>
<section id="proposed-interface">
<h2><a class="toc-backref" href="#proposed-interface" role="doc-backlink">Proposed Interface</a></h2>
<p>XXX open issues: naming convention (studlycaps or
underline-separated?); need to look at the <code class="docutils literal notranslate"><span class="pre">cgi.parse*()</span></code> functions
and see if they can be simplified, too.</p>
<p>Parsing functions: carry over most of the <code class="docutils literal notranslate"><span class="pre">parse*</span></code> functions from
cgi.py</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># The Response class borrows most of its methods from Zope&#39;s</span>
<span class="c1"># HTTPResponse class.</span>
<span class="k">class</span> <span class="nc">Response</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Attributes:</span>
<span class="sd"> status: HTTP status code to return</span>
<span class="sd"> headers: dictionary of response headers</span>
<span class="sd"> body: string containing the body of the HTTP response</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="p">{},</span> <span class="n">body</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">setStatus</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="n">reason</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="s2">&quot;Set the numeric HTTP response code&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">setHeader</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="s2">&quot;Set an HTTP header&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">setBody</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">body</span><span class="p">):</span>
<span class="s2">&quot;Set the body of the response&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">setCookie</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span>
<span class="n">path</span> <span class="o">=</span> <span class="s1">&#39;/&#39;</span><span class="p">,</span>
<span class="n">comment</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
<span class="n">domain</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
<span class="nb">max</span><span class="o">-</span><span class="n">age</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
<span class="n">expires</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
<span class="n">secure</span> <span class="o">=</span> <span class="mi">0</span>
<span class="p">):</span>
<span class="s2">&quot;Set a cookie&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">expireCookie</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="s2">&quot;Remove a cookie from the user&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">redirect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">):</span>
<span class="s2">&quot;Redirect the browser to another URL&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;Convert entire response to a string&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">dump</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;Return a string representation useful for debugging&quot;</span>
<span class="k">pass</span>
<span class="c1"># XXX methods for specific classes of error:serverError,</span>
<span class="c1"># badRequest, etc.?</span>
<span class="k">class</span> <span class="nc">Request</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Attributes:</span>
<span class="sd"> XXX should these be dictionaries, or dictionary-like objects?</span>
<span class="sd"> .headers : dictionary containing HTTP headers</span>
<span class="sd"> .cookies : dictionary of cookies</span>
<span class="sd"> .fields : data from the form</span>
<span class="sd"> .env : environment dictionary</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">,</span> <span class="n">stdin</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="p">,</span>
<span class="n">keep_blank_values</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">strict_parsing</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Initialize the request object, using the provided environment</span>
<span class="sd"> and standard input.&quot;&quot;&quot;</span>
<span class="k">pass</span>
<span class="c1"># Should people just use the dictionaries directly?</span>
<span class="k">def</span> <span class="nf">getHeader</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">getCookie</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">getField</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="s2">&quot;Return field&#39;s value as a string (even if it&#39;s an uploaded file)&quot;</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">getUploadedFile</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns a file object that can be read to obtain the contents</span>
<span class="sd"> of an uploaded file. XXX should this report an error if the</span>
<span class="sd"> field isn&#39;t actually an uploaded file? Or should it wrap</span>
<span class="sd"> a StringIO around simple fields for consistency?</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span> <span class="nf">getURL</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">query_string</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the URL of the current request, chopping off &#39;n&#39; path</span>
<span class="sd"> components from the right. Eg. if the URL is</span>
<span class="sd"> &quot;http://foo.com/bar/baz/quux&quot;, n=2 would return</span>
<span class="sd"> &quot;http://foo.com/bar&quot;. Does not include the query string (if</span>
<span class="sd"> any)</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span> <span class="nf">getBaseURL</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return the base URL of the current request, adding &#39;n&#39; path</span>
<span class="sd"> components to the end to recreate more of the whole URL.</span>
<span class="sd"> Eg. if the request URL is</span>
<span class="sd"> &quot;http://foo.com/q/bar/baz/qux&quot;, n=0 would return</span>
<span class="sd"> &quot;http://foo.com/&quot;, and n=2 &quot;http://foo.com/q/bar&quot;.</span>
<span class="sd"> Returned URL does not include the query string, if any.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span> <span class="nf">dump</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;String representation suitable for debugging output&quot;</span>
<span class="k">pass</span>
<span class="c1"># Possibilities? I don&#39;t know if these are worth doing in the</span>
<span class="c1"># basic objects.</span>
<span class="k">def</span> <span class="nf">getBrowser</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;Returns Mozilla/IE/Lynx/Opera/whatever&quot;</span>
<span class="k">def</span> <span class="nf">isSecure</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;Return true if this is an SSLified request&quot;</span>
<span class="c1"># Module-level function</span>
<span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">logfile</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Calls the function &#39;func&#39;, passing it the arguments</span>
<span class="sd"> (request, response, logfile). Exceptions are trapped and</span>
<span class="sd"> sent to the file &#39;logfile&#39;.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># This wrapper will detect if it&#39;s being called from the command-line,</span>
<span class="c1"># and if so, it will run in a debugging mode; name=value pairs</span>
<span class="c1"># can be entered on standard input to set field values.</span>
<span class="c1"># (XXX how to do file uploads in this syntax?)</span>
</pre></div>
</div>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0222.rst">https://github.com/python/peps/blob/main/peps/pep-0222.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0222.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#new-modules">New Modules</a></li>
<li><a class="reference internal" href="#major-changes-to-existing-modules">Major Changes to Existing Modules</a></li>
<li><a class="reference internal" href="#minor-changes-to-existing-modules">Minor Changes to Existing Modules</a></li>
<li><a class="reference internal" href="#rejected-changes">Rejected Changes</a></li>
<li><a class="reference internal" href="#proposed-interface">Proposed Interface</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0222.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

331
pep-0223/index.html Normal file
View File

@ -0,0 +1,331 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 223 Change the Meaning of \x Escapes | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0223/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 223 Change the Meaning of \x Escapes | peps.python.org'>
<meta property="og:description" content="Change \x escapes, in both 8-bit and Unicode strings, to consume exactly the two hex digits following. The proposal views this as correcting an original design flaw, leading to clearer expression in all flavors of string, a cleaner Unicode story, bette...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0223/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Change \x escapes, in both 8-bit and Unicode strings, to consume exactly the two hex digits following. The proposal views this as correcting an original design flaw, leading to clearer expression in all flavors of string, a cleaner Unicode story, bette...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 223</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 223 Change the Meaning of <code class="docutils literal notranslate"><span class="pre">\x</span></code> Escapes</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Tim Peters &lt;tim.peters&#32;&#97;t&#32;gmail.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">20-Aug-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.0</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">23-Aug-2000</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#syntax">Syntax</a></li>
<li><a class="reference internal" href="#semantics">Semantics</a></li>
<li><a class="reference internal" href="#example">Example</a></li>
<li><a class="reference internal" href="#history-and-rationale">History and Rationale</a></li>
<li><a class="reference internal" href="#development-and-discussion">Development and Discussion</a></li>
<li><a class="reference internal" href="#backward-compatibility">Backward Compatibility</a></li>
<li><a class="reference internal" href="#effects-on-other-tools">Effects on Other Tools</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#bdfl-pronouncements">BDFL Pronouncements</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Change <code class="docutils literal notranslate"><span class="pre">\x</span></code> escapes, in both 8-bit and Unicode strings, to consume
exactly the two hex digits following. The proposal views this as
correcting an original design flaw, leading to clearer expression
in all flavors of string, a cleaner Unicode story, better
compatibility with Perl regular expressions, and with minimal risk
to existing code.</p>
</section>
<section id="syntax">
<h2><a class="toc-backref" href="#syntax" role="doc-backlink">Syntax</a></h2>
<p>The syntax of <code class="docutils literal notranslate"><span class="pre">\x</span></code> escapes, in all flavors of non-raw strings, becomes</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>\<span class="n">xhh</span>
</pre></div>
</div>
<p>where h is a hex digit (0-9, a-f, A-F). The exact syntax in 1.5.2 is
not clearly specified in the Reference Manual; it says</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>\<span class="n">xhh</span><span class="o">...</span>
</pre></div>
</div>
<p>implying “two or more” hex digits, but one-digit forms are also
accepted by the 1.5.2 compiler, and a plain <code class="docutils literal notranslate"><span class="pre">\x</span></code> is “expanded” to
itself (i.e., a backslash followed by the letter x). Its unclear
whether the Reference Manual intended either of the 1-digit or
0-digit behaviors.</p>
</section>
<section id="semantics">
<h2><a class="toc-backref" href="#semantics" role="doc-backlink">Semantics</a></h2>
<p>In an 8-bit non-raw string,</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>\<span class="n">xij</span>
</pre></div>
</div>
<p>expands to the character</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">chr</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">ij</span><span class="p">,</span> <span class="mi">16</span><span class="p">))</span>
</pre></div>
</div>
<p>Note that this is the same as in 1.6 and before.</p>
<p>In a Unicode string,</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>\<span class="n">xij</span>
</pre></div>
</div>
<p>acts the same as</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>\<span class="n">u00ij</span>
</pre></div>
</div>
<p>i.e. it expands to the obvious Latin-1 character from the initial
segment of the Unicode space.</p>
<p>An <code class="docutils literal notranslate"><span class="pre">\x</span></code> not followed by at least two hex digits is a compile-time error,
specifically <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> in 8-bit strings, and <code class="docutils literal notranslate"><span class="pre">UnicodeError</span></code> (a subclass
of <code class="docutils literal notranslate"><span class="pre">ValueError</span></code>) in Unicode strings. Note that if an <code class="docutils literal notranslate"><span class="pre">\x</span></code> is followed by
more than two hex digits, only the first two are “consumed”. In 1.6
and before all but the <em>last</em> two were silently ignored.</p>
</section>
<section id="example">
<h2><a class="toc-backref" href="#example" role="doc-backlink">Example</a></h2>
<p>In 1.5.2:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="s2">&quot;</span><span class="se">\x12</span><span class="s2">3465&quot;</span> <span class="c1"># same as &quot;\x65&quot;</span>
<span class="go">&#39;e&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="s2">&quot;</span><span class="se">\x65</span><span class="s2">&quot;</span>
<span class="go">&#39;e&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="s2">&quot;\x1&quot;</span>
<span class="go">&#39;\001&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="s2">&quot;\x\x&quot;</span>
<span class="go">&#39;\\x\\x&#39;</span>
<span class="gp">&gt;&gt;&gt;</span>
</pre></div>
</div>
<p>In 2.0:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="s2">&quot;</span><span class="se">\x12</span><span class="s2">3465&quot;</span> <span class="c1"># \x12 -&gt; \022, &quot;3456&quot; left alone</span>
<span class="go">&#39;\0223456&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="s2">&quot;</span><span class="se">\x65</span><span class="s2">&quot;</span>
<span class="go">&#39;e&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="s2">&quot;\x1&quot;</span>
<span class="go">[ValueError is raised]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="s2">&quot;\x\x&quot;</span>
<span class="go">[ValueError is raised]</span>
<span class="gp">&gt;&gt;&gt;</span>
</pre></div>
</div>
</section>
<section id="history-and-rationale">
<h2><a class="toc-backref" href="#history-and-rationale" role="doc-backlink">History and Rationale</a></h2>
<p><code class="docutils literal notranslate"><span class="pre">\x</span></code> escapes were introduced in C as a way to specify variable-width
character encodings. Exactly which encodings those were, and how many
hex digits they required, was left up to each implementation. The
language simply stated that <code class="docutils literal notranslate"><span class="pre">\x</span></code> “consumed” <em>all</em> hex digits following,
and left the meaning up to each implementation. So, in effect, <code class="docutils literal notranslate"><span class="pre">\x</span></code> in C
is a standard hook to supply platform-defined behavior.</p>
<p>Because Python explicitly aims at platform independence, the <code class="docutils literal notranslate"><span class="pre">\x</span></code> escape
in Python (up to and including 1.6) has been treated the same way
across all platforms: all <em>except</em> the last two hex digits were
silently ignored. So the only actual use for <code class="docutils literal notranslate"><span class="pre">\x</span></code> escapes in Python was
to specify a single byte using hex notation.</p>
<p>Larry Wall appears to have realized that this was the only real use for
<code class="docutils literal notranslate"><span class="pre">\x</span></code> escapes in a platform-independent language, as the proposed rule for
Python 2.0 is in fact what Perl has done from the start (although you
need to run in Perl -w mode to get warned about <code class="docutils literal notranslate"><span class="pre">\x</span></code> escapes with fewer
than 2 hex digits following its clearly more Pythonic to insist on
2 all the time).</p>
<p>When Unicode strings were introduced to Python, <code class="docutils literal notranslate"><span class="pre">\x</span></code> was generalized so
as to ignore all but the last <em>four</em> hex digits in Unicode strings.
This caused a technical difficulty for the new regular expression engine:
SRE tries very hard to allow mixing 8-bit and Unicode patterns and
strings in intuitive ways, and it no longer had any way to guess what,
for example, <code class="docutils literal notranslate"><span class="pre">r&quot;\x123456&quot;</span></code> should mean as a pattern: is it asking to match
the 8-bit character <code class="docutils literal notranslate"><span class="pre">\x56</span></code> or the Unicode character <code class="docutils literal notranslate"><span class="pre">\u3456</span></code>?</p>
<p>There are hacky ways to guess, but it doesnt end there. The ISO C99
standard also introduces 8-digit <code class="docutils literal notranslate"><span class="pre">\U12345678</span></code> escapes to cover the entire
ISO 10646 character space, and its also desired that Python 2 support
that from the start. But then what are <code class="docutils literal notranslate"><span class="pre">\x</span></code> escapes supposed to mean?
Do they ignore all but the last <em>eight</em> hex digits then? And if less
than 8 following in a Unicode string, all but the last 4? And if less
than 4, all but the last 2?</p>
<p>This was getting messier by the minute, and the proposal cuts the
Gordian knot by making <code class="docutils literal notranslate"><span class="pre">\x</span></code> simpler instead of more complicated. Note
that the 4-digit generalization to <code class="docutils literal notranslate"><span class="pre">\xijkl</span></code> in Unicode strings was also
redundant, because it meant exactly the same thing as <code class="docutils literal notranslate"><span class="pre">\uijkl</span></code> in Unicode
strings. Its more Pythonic to have just one obvious way to specify a
Unicode character via hex notation.</p>
</section>
<section id="development-and-discussion">
<h2><a class="toc-backref" href="#development-and-discussion" role="doc-backlink">Development and Discussion</a></h2>
<p>The proposal was worked out among Guido van Rossum, Fredrik Lundh and
Tim Peters in email. It was subsequently explained and discussed on
Python-Dev under subject “Go x yourself” <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>, starting 2000-08-03.
Response was overwhelmingly positive; no objections were raised.</p>
</section>
<section id="backward-compatibility">
<h2><a class="toc-backref" href="#backward-compatibility" role="doc-backlink">Backward Compatibility</a></h2>
<p>Changing the meaning of <code class="docutils literal notranslate"><span class="pre">\x</span></code> escapes does carry risk of breaking existing
code, although no instances of incompatibility have yet been discovered.
The risk is believed to be minimal.</p>
<p>Tim Peters verified that, except for pieces of the standard test suite
deliberately provoking end cases, there are no instances of <code class="docutils literal notranslate"><span class="pre">\xabcdef...</span></code>
with fewer or more than 2 hex digits following, in either the Python
CVS development tree, or in assorted Python packages sitting on his
machine.</p>
<p>Its unlikely there are any with fewer than 2, because the Reference
Manual implied they werent legal (although this is debatable!). If
there are any with more than 2, Guido is ready to argue they were buggy
anyway &lt;0.9 wink&gt;.</p>
<p>Guido reported that the OReilly Python books <em>already</em> document that
Python works the proposed way, likely due to their Perl editing
heritage (as above, Perl worked (very close to) the proposed way from
its start).</p>
<p>Finn Bock reported that what JPython does with <code class="docutils literal notranslate"><span class="pre">\x</span></code> escapes is
unpredictable today. This proposal gives a clear meaning that can be
consistently and easily implemented across all Python implementations.</p>
</section>
<section id="effects-on-other-tools">
<h2><a class="toc-backref" href="#effects-on-other-tools" role="doc-backlink">Effects on Other Tools</a></h2>
<p>Believed to be none. The candidates for breakage would mostly be
parsing tools, but the author knows of none that worry about the
internal structure of Python strings beyond the approximation “when
theres a backslash, swallow the next character”. Tim Peters checked
<code class="docutils literal notranslate"><span class="pre">python-mode.el</span></code>, the std <code class="docutils literal notranslate"><span class="pre">tokenize.py</span></code> and <code class="docutils literal notranslate"><span class="pre">pyclbr.py</span></code>, and the IDLE syntax
coloring subsystem, and believes theres no need to change any of
them. Tools like <code class="docutils literal notranslate"><span class="pre">tabnanny.py</span></code> and <code class="docutils literal notranslate"><span class="pre">checkappend.py</span></code> inherit their immunity
from <code class="docutils literal notranslate"><span class="pre">tokenize.py</span></code>.</p>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>The code changes are so simple that a separate patch will not be produced.
Fredrik Lundh is writing the code, is an expert in the area, and will
simply check the changes in before 2.0b1 is released.</p>
</section>
<section id="bdfl-pronouncements">
<h2><a class="toc-backref" href="#bdfl-pronouncements" role="doc-backlink">BDFL Pronouncements</a></h2>
<p>Yes, <code class="docutils literal notranslate"><span class="pre">ValueError</span></code>, not <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code>. “Problems with literal interpretations
traditionally raise runtime exceptions rather than syntax errors.”</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd>Tim Peters, Go x yourself
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2000-August/007825.html">https://mail.python.org/pipermail/python-dev/2000-August/007825.html</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0223.rst">https://github.com/python/peps/blob/main/peps/pep-0223.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0223.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#syntax">Syntax</a></li>
<li><a class="reference internal" href="#semantics">Semantics</a></li>
<li><a class="reference internal" href="#example">Example</a></li>
<li><a class="reference internal" href="#history-and-rationale">History and Rationale</a></li>
<li><a class="reference internal" href="#development-and-discussion">Development and Discussion</a></li>
<li><a class="reference internal" href="#backward-compatibility">Backward Compatibility</a></li>
<li><a class="reference internal" href="#effects-on-other-tools">Effects on Other Tools</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#bdfl-pronouncements">BDFL Pronouncements</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0223.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

364
pep-0224/index.html Normal file
View File

@ -0,0 +1,364 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 224 Attribute Docstrings | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0224/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 224 Attribute Docstrings | peps.python.org'>
<meta property="og:description" content="This PEP describes the “attribute docstring” proposal for Python 2.0. This PEP tracks the status and ownership of this feature. It contains a description of the feature and outlines changes necessary to support the feature. The CVS revision history of...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0224/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the “attribute docstring” proposal for Python 2.0. This PEP tracks the status and ownership of this feature. It contains a description of the feature and outlines changes necessary to support the feature. The CVS revision history of...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 224</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 224 Attribute Docstrings</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Marc-André Lemburg &lt;mal&#32;&#97;t&#32;lemburg.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">23-Aug-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#caveats-of-the-implementation">Caveats of the Implementation</a></li>
<li><a class="reference internal" href="#possible-problems">Possible Problems</a></li>
<li><a class="reference internal" href="#comments-from-our-bdfl">Comments from our BDFL</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated rejected admonition warning">
<p class="admonition-title">Warning</p>
<p>This PEP has been rejected.</p>
<p class="close-button">×</p>
<p>See <a class="reference internal" href="#rejection"><span class="std std-ref">Comments from our BDFL</span></a> for more information.</p>
<p></p>
</div>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes the “attribute docstring” proposal for Python
2.0. This PEP tracks the status and ownership of this feature.
It contains a description of the feature and outlines changes
necessary to support the feature. The CVS revision history of
this file contains the definitive historical record.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>This PEP proposes a small addition to the way Python currently
handles docstrings embedded in Python code.</p>
<p>Python currently only handles the case of docstrings which appear
directly after a class definition, a function definition or as
first string literal in a module. The string literals are added
to the objects in question under the <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> attribute and are
from then on available for introspection tools which can extract
the contained information for help, debugging and documentation
purposes.</p>
<p>Docstrings appearing in locations other than the ones mentioned
are simply ignored and dont result in any code generation.</p>
<p>Here is an example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="s2">&quot;class C doc-string&quot;</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="s2">&quot;attribute C.a doc-string (1)&quot;</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">2</span>
<span class="s2">&quot;attribute C.b doc-string (2)&quot;</span>
</pre></div>
</div>
<p>The docstrings (1) and (2) are currently being ignored by the
Python byte code compiler, but could obviously be put to good use
for documenting the named assignments that precede them.</p>
<p>This PEP proposes to also make use of these cases by proposing
semantics for adding their content to the objects in which they
appear under new generated attribute names.</p>
<p>The original idea behind this approach which also inspired the
above example was to enable inline documentation of class
attributes, which can currently only be documented in the classs
docstring or using comments which are not available for
introspection.</p>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>Docstrings are handled by the byte code compiler as expressions.
The current implementation special cases the few locations
mentioned above to make use of these expressions, but otherwise
ignores the strings completely.</p>
<p>To enable use of these docstrings for documenting named
assignments (which is the natural way of defining e.g. class
attributes), the compiler will have to keep track of the last
assigned name and then use this name to assign the content of the
docstring to an attribute of the containing object by means of
storing it in as a constant which is then added to the objects
namespace during object construction time.</p>
<p>In order to preserve features like inheritance and hiding of
Pythons special attributes (ones with leading and trailing double
underscores), a special name mangling has to be applied which
uniquely identifies the docstring as belonging to the name
assignment and allows finding the docstring later on by inspecting
the namespace.</p>
<p>The following name mangling scheme achieves all of the above:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">__doc_</span><span class="o">&lt;</span><span class="n">attributename</span><span class="o">&gt;</span><span class="n">__</span>
</pre></div>
</div>
<p>To keep track of the last assigned name, the byte code compiler
stores this name in a variable of the compiling structure. This
variable defaults to NULL. When it sees a docstring, it then
checks the variable and uses the name as basis for the above name
mangling to produce an implicit assignment of the docstring to the
mangled name. It then resets the variable to NULL to avoid
duplicate assignments.</p>
<p>If the variable does not point to a name (i.e. is NULL), no
assignments are made. These will continue to be ignored like
before. All classical docstrings fall under this case, so no
duplicate assignments are done.</p>
<p>In the above example this would result in the following new class
attributes to be created:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">C</span><span class="o">.</span><span class="n">__doc_a__</span> <span class="o">==</span> <span class="s2">&quot;attribute C.a doc-string (1)&quot;</span>
<span class="n">C</span><span class="o">.</span><span class="n">__doc_b__</span> <span class="o">==</span> <span class="s2">&quot;attribute C.b doc-string (2)&quot;</span>
</pre></div>
</div>
<p>A patch to the current CVS version of Python 2.0 which implements
the above is available on SourceForge at <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>.</p>
</section>
<section id="caveats-of-the-implementation">
<h2><a class="toc-backref" href="#caveats-of-the-implementation" role="doc-backlink">Caveats of the Implementation</a></h2>
<p>Since the implementation does not reset the compiling structure
variable when processing a non-expression, e.g. a function
definition, the last assigned name remains active until either the
next assignment or the next occurrence of a docstring.</p>
<p>This can lead to cases where the docstring and assignment may be
separated by other expressions:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="s2">&quot;C doc string&quot;</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">def</span> <span class="nf">x</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;C.x doc string&quot;</span>
<span class="n">y</span> <span class="o">=</span> <span class="mi">3</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="s2">&quot;b&#39;s doc string&quot;</span>
</pre></div>
</div>
<p>Since the definition of method “x” currently does not reset the
used assignment name variable, it is still valid when the compiler
reaches the docstring “bs doc string” and thus assigns the string
to <code class="docutils literal notranslate"><span class="pre">__doc_b__</span></code>.</p>
<p>A possible solution to this problem would be resetting the name
variable for all non-expression nodes in the compiler.</p>
</section>
<section id="possible-problems">
<h2><a class="toc-backref" href="#possible-problems" role="doc-backlink">Possible Problems</a></h2>
<p>Even though highly unlikely, attribute docstrings could get
accidentally concatenated to the attributes value:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="n">x</span> <span class="o">=</span> <span class="s2">&quot;text&quot;</span> \
<span class="s2">&quot;x&#39;s docstring&quot;</span>
</pre></div>
</div>
<p>The trailing slash would cause the Python compiler to concatenate
the attribute value and the docstring.</p>
<p>A modern syntax highlighting editor would easily make this
accident visible, though, and by simply inserting empty lines
between the attribute definition and the docstring you can avoid
the possible concatenation completely, so the problem is
negligible.</p>
<p>Another possible problem is that of using triple quoted strings as
a way to uncomment parts of your code.</p>
<p>If there happens to be an assignment just before the start of the
comment string, then the compiler will treat the comment as
docstring attribute and apply the above logic to it.</p>
<p>Besides generating a docstring for an otherwise undocumented
attribute there is no breakage.</p>
</section>
<section id="comments-from-our-bdfl">
<span id="rejection"></span><h2><a class="toc-backref" href="#comments-from-our-bdfl" role="doc-backlink">Comments from our BDFL</a></h2>
<p>Early comments on the PEP from Guido:</p>
<blockquote>
<div>I “kinda” like the idea of having attribute docstrings (meaning
its not of great importance to me) but there are two things I
dont like in your current proposal:<ol class="arabic simple">
<li>The syntax you propose is too ambiguous: as you say,
stand-alone string literal are used for other purposes and could
suddenly become attribute docstrings.</li>
<li>I dont like the access method either (<code class="docutils literal notranslate"><span class="pre">__doc_&lt;attrname&gt;__</span></code>).</li>
</ol>
</div></blockquote>
<p>The authors reply:</p>
<blockquote>
<div><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="mf">1.</span> <span class="n">The</span> <span class="n">syntax</span> <span class="n">you</span> <span class="n">propose</span> <span class="ow">is</span> <span class="n">too</span> <span class="n">ambiguous</span><span class="p">:</span> <span class="k">as</span> <span class="n">you</span> <span class="n">say</span><span class="p">,</span> <span class="n">stand</span><span class="o">-</span><span class="n">alone</span>
<span class="o">&gt;</span> <span class="n">string</span> <span class="n">literal</span> <span class="n">are</span> <span class="n">used</span> <span class="k">for</span> <span class="n">other</span> <span class="n">purposes</span> <span class="ow">and</span> <span class="n">could</span> <span class="n">suddenly</span>
<span class="o">&gt;</span> <span class="n">become</span> <span class="n">attribute</span> <span class="n">docstrings</span><span class="o">.</span>
</pre></div>
</div>
<p>This can be fixed by introducing some extra checks in the
compiler to reset the “doc attribute” flag in the compiler
struct.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="mf">2.</span> <span class="n">I</span> <span class="n">don</span><span class="s1">&#39;t like the access method either (``__doc_&lt;attrname&gt;__``).</span>
</pre></div>
</div>
<p>Any other name will do. It will only have to match these
criteria:</p>
<ul class="simple">
<li>must start with two underscores (to match <code class="docutils literal notranslate"><span class="pre">__doc__</span></code>)</li>
<li>must be extractable using some form of inspection (e.g. by using
a naming convention which includes some fixed name part)</li>
<li>must be compatible with class inheritance (i.e. should be
stored as attribute)</li>
</ul>
</div></blockquote>
<p>Later on in March, Guido pronounced on this PEP in March 2001 (on
python-dev). Here are his reasons for rejection mentioned in
private mail to the author of this PEP:</p>
<blockquote>
<div><p>It might be useful, but I really hate the proposed syntax.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="s2">&quot;foo bar&quot;</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">1</span>
</pre></div>
</div>
<p>I really have no way to know whether “foo bar” is a docstring
for a or for b.</p>
<p></p>
<p>You can use this convention:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">__doc_a__</span> <span class="o">=</span> <span class="s2">&quot;doc string for a&quot;</span>
</pre></div>
</div>
<p>This makes it available at runtime.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&gt; Are you completely opposed to adding attribute documentation
&gt; to Python or is it just the way the implementation works ? I
&gt; find the syntax proposed in the PEP very intuitive and many
&gt; other users on c.l.p and in private emails have supported it
&gt; at the time I wrote the PEP.
</pre></div>
</div>
<p>Its not the implementation, its the syntax. It doesnt
convey a clear enough coupling between the variable and the
doc string.</p>
</div></blockquote>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the Public Domain.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=101264&amp;group_id=5470">http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=101264&amp;group_id=5470</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0224.rst">https://github.com/python/peps/blob/main/peps/pep-0224.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0224.rst">2024-04-14 20:08:31 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#caveats-of-the-implementation">Caveats of the Implementation</a></li>
<li><a class="reference internal" href="#possible-problems">Possible Problems</a></li>
<li><a class="reference internal" href="#comments-from-our-bdfl">Comments from our BDFL</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references">References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0224.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

847
pep-0225/index.html Normal file
View File

@ -0,0 +1,847 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 225 Elementwise/Objectwise Operators | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0225/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 225 Elementwise/Objectwise Operators | peps.python.org'>
<meta property="og:description" content="This PEP describes a proposal to add new operators to Python which are useful for distinguishing elementwise and objectwise operations, and summarizes discussions in the news group comp.lang.python on this topic. See Credits and Archives section at end...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0225/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes a proposal to add new operators to Python which are useful for distinguishing elementwise and objectwise operations, and summarizes discussions in the news group comp.lang.python on this topic. See Credits and Archives section at end...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 225</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 225 Elementwise/Objectwise Operators</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Huaiyu Zhu &lt;hzhu&#32;&#97;t&#32;users.sourceforge.net&gt;,
Gregory Lielens &lt;gregory.lielens&#32;&#97;t&#32;fft.be&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">19-Sep-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#proposed-extension">Proposed extension</a></li>
<li><a class="reference internal" href="#prototype-implementation">Prototype Implementation</a></li>
<li><a class="reference internal" href="#alternatives-to-adding-new-operators">Alternatives to adding new operators</a></li>
<li><a class="reference internal" href="#alternative-forms-of-infix-operators">Alternative forms of infix operators</a></li>
<li><a class="reference internal" href="#semantics-of-new-operators">Semantics of new operators</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#miscellaneous-issues">Miscellaneous issues</a></li>
<li><a class="reference internal" href="#impact-on-general-elementization">Impact on general elementization</a><ul>
<li><a class="reference internal" href="#notes">Notes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#impact-on-named-operators">Impact on named operators</a></li>
<li><a class="reference internal" href="#credits-and-archives">Credits and archives</a></li>
<li><a class="reference internal" href="#additional-references">Additional References</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated rejected admonition warning">
<p class="admonition-title">Warning</p>
<p>This PEP has been rejected.</p>
<p class="close-button">×</p>
<p>The approach in the later <a class="pep reference internal" href="../pep-0465/" title="PEP 465 A dedicated infix operator for matrix multiplication">PEP 465</a> was eventually accepted
in lieu of this PEP. The <a class="pep reference internal" href="../pep-0465/#rejected-alternatives-to-adding-a-new-operator" title="PEP 465 A dedicated infix operator for matrix multiplication § Rejected alternatives to adding a new operator">Rejected Ideas</a>
of that PEP explains the rationale in more detail.</p>
<p></p>
</div>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes a proposal to add new operators to Python which are useful
for distinguishing elementwise and objectwise operations, and summarizes
discussions in the news group comp.lang.python on this topic. See Credits and
Archives section at end. Issues discussed here include:</p>
<ul class="simple">
<li>Background.</li>
<li>Description of proposed operators and implementation issues.</li>
<li>Analysis of alternatives to new operators.</li>
<li>Analysis of alternative forms.</li>
<li>Compatibility issues</li>
<li>Description of wider extensions and other related ideas.</li>
</ul>
<p>A substantial portion of this PEP describes ideas that do not go into the
proposed extension. They are presented because the extension is essentially
syntactic sugar, so its adoption must be weighed against various possible
alternatives. While many alternatives may be better in some aspects, the
current proposal appears to be overall advantageous.</p>
<p>The issues concerning elementwise-objectwise operations extends to wider areas
than numerical computation. This document also describes how the current
proposal may be integrated with more general future extensions.</p>
</section>
<section id="background">
<h2><a class="toc-backref" href="#background" role="doc-backlink">Background</a></h2>
<p>Python provides six binary infix math operators: <code class="docutils literal notranslate"><span class="pre">+</span></code> <code class="docutils literal notranslate"><span class="pre">-</span></code> <code class="docutils literal notranslate"><span class="pre">*</span></code> <code class="docutils literal notranslate"><span class="pre">/</span></code> <code class="docutils literal notranslate"><span class="pre">%</span></code>
<code class="docutils literal notranslate"><span class="pre">**</span></code> hereafter generically represented by <code class="docutils literal notranslate"><span class="pre">op</span></code>. They can be overloaded
with new semantics for user-defined classes. However, for objects composed of
homogeneous elements, such as arrays, vectors and matrices in numerical
computation, there are two essentially distinct flavors of semantics. The
objectwise operations treat these objects as points in multidimensional spaces.
The elementwise operations treat them as collections of individual elements.
These two flavors of operations are often intermixed in the same formulas,
thereby requiring syntactical distinction.</p>
<p>Many numerical computation languages provide two sets of math operators. For
example, in MatLab, the ordinary <code class="docutils literal notranslate"><span class="pre">op</span></code> is used for objectwise operation while
<code class="docutils literal notranslate"><span class="pre">.op</span></code> is used for elementwise operation. In R, <code class="docutils literal notranslate"><span class="pre">op</span></code> stands for elementwise
operation while <code class="docutils literal notranslate"><span class="pre">%op%</span></code> stands for objectwise operation.</p>
<p>In Python, there are other methods of representation, some of which already
used by available numerical packages, such as:</p>
<ul class="simple">
<li>function: mul(a,b)</li>
<li>method: a.mul(b)</li>
<li>casting: a.E*b</li>
</ul>
<p>In several aspects these are not as adequate as infix operators. More details
will be shown later, but the key points are:</p>
<ul class="simple">
<li>Readability: Even for moderately complicated formulas, infix operators are
much cleaner than alternatives.</li>
<li>Familiarity: Users are familiar with ordinary math operators.</li>
<li>Implementation: New infix operators will not unduly clutter Python syntax.
They will greatly ease the implementation of numerical packages.</li>
</ul>
<p>While it is possible to assign current math operators to one flavor of
semantics, there is simply not enough infix operators to overload for the other
flavor. It is also impossible to maintain visual symmetry between these two
flavors if one of them does not contain symbols for ordinary math operators.</p>
</section>
<section id="proposed-extension">
<h2><a class="toc-backref" href="#proposed-extension" role="doc-backlink">Proposed extension</a></h2>
<ul class="simple">
<li>Six new binary infix operators <code class="docutils literal notranslate"><span class="pre">~+</span></code> <code class="docutils literal notranslate"><span class="pre">~-</span></code> <code class="docutils literal notranslate"><span class="pre">~*</span></code> <code class="docutils literal notranslate"><span class="pre">~/</span></code> <code class="docutils literal notranslate"><span class="pre">~%</span></code> <code class="docutils literal notranslate"><span class="pre">~**</span></code> are
added to core Python. They parallel the existing operators <code class="docutils literal notranslate"><span class="pre">+</span></code> <code class="docutils literal notranslate"><span class="pre">-</span></code> <code class="docutils literal notranslate"><span class="pre">*</span></code>
<code class="docutils literal notranslate"><span class="pre">/</span></code> <code class="docutils literal notranslate"><span class="pre">%</span></code> <code class="docutils literal notranslate"><span class="pre">**</span></code>.</li>
<li>Six augmented assignment operators <code class="docutils literal notranslate"><span class="pre">~+=</span></code> <code class="docutils literal notranslate"><span class="pre">~-=</span></code> <code class="docutils literal notranslate"><span class="pre">~*=</span></code> <code class="docutils literal notranslate"><span class="pre">~/=</span></code> <code class="docutils literal notranslate"><span class="pre">~%=</span></code>
<code class="docutils literal notranslate"><span class="pre">~**=</span></code> are added to core Python. They parallel the operators <code class="docutils literal notranslate"><span class="pre">+=</span></code> <code class="docutils literal notranslate"><span class="pre">-=</span></code>
<code class="docutils literal notranslate"><span class="pre">*=</span></code> <code class="docutils literal notranslate"><span class="pre">/=</span></code> <code class="docutils literal notranslate"><span class="pre">%=</span></code> <code class="docutils literal notranslate"><span class="pre">**=</span></code> available in Python 2.0.</li>
<li>Operator <code class="docutils literal notranslate"><span class="pre">~op</span></code> retains the syntactical properties of operator <code class="docutils literal notranslate"><span class="pre">op</span></code>,
including precedence.</li>
<li>Operator <code class="docutils literal notranslate"><span class="pre">~op</span></code> retains the semantical properties of operator <code class="docutils literal notranslate"><span class="pre">op</span></code> on
built-in number types.</li>
<li>Operator <code class="docutils literal notranslate"><span class="pre">~op</span></code> raise syntax error on non-number builtin types. This is
temporary until the proper behavior can be agreed upon.</li>
<li>These operators are overloadable in classes with names that prepend <em>t</em> (for
tilde) to names of ordinary math operators. For example, <code class="docutils literal notranslate"><span class="pre">__tadd__</span></code> and
<code class="docutils literal notranslate"><span class="pre">__rtadd__</span></code> work for <code class="docutils literal notranslate"><span class="pre">~+</span></code> just as <code class="docutils literal notranslate"><span class="pre">__add__</span></code> and <code class="docutils literal notranslate"><span class="pre">__radd__</span></code> work for
<code class="docutils literal notranslate"><span class="pre">+</span></code>.</li>
<li>As with existing operators, the <code class="docutils literal notranslate"><span class="pre">__r*__()</span></code> methods are invoked when the
left operand does not provide the appropriate method.</li>
</ul>
<p>It is intended that one set of <code class="docutils literal notranslate"><span class="pre">op</span></code> or <code class="docutils literal notranslate"><span class="pre">~op</span></code> is used for elementwise
operations, the other for objectwise operations, but it is not specified which
version of operators stands for elementwise or objectwise operations, leaving
the decision to applications.</p>
<p>The proposed implementation is to patch several files relating to the
tokenizer, parser, grammar and compiler to duplicate the functionality of
corresponding existing operators as necessary. All new semantics are to be
implemented in the classes that overload them.</p>
<p>The symbol <code class="docutils literal notranslate"><span class="pre">~</span></code> is already used in Python as the unary <em>bitwise not</em> operator.
Currently it is not allowed for binary operators. The new operators are
completely backward compatible.</p>
</section>
<section id="prototype-implementation">
<h2><a class="toc-backref" href="#prototype-implementation" role="doc-backlink">Prototype Implementation</a></h2>
<p>Greg Lielens implemented the infix <code class="docutils literal notranslate"><span class="pre">~op</span></code> as a patch against Python 2.0b1
source <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>.</p>
<p>To allow <code class="docutils literal notranslate"><span class="pre">~</span></code> to be part of binary operators, the tokenizer would treat <code class="docutils literal notranslate"><span class="pre">~+</span></code>
as one token. This means that currently valid expression <code class="docutils literal notranslate"><span class="pre">~+1</span></code> would be
tokenized as <code class="docutils literal notranslate"><span class="pre">~+</span></code> <code class="docutils literal notranslate"><span class="pre">1</span></code> instead of <code class="docutils literal notranslate"><span class="pre">~</span> <span class="pre">+</span> <span class="pre">1</span></code>. The parser would then treat <code class="docutils literal notranslate"><span class="pre">~+</span></code>
as composite of <code class="docutils literal notranslate"><span class="pre">~</span> <span class="pre">+</span></code>. The effect is invisible to applications.</p>
<p>Notes about current patch:</p>
<ul class="simple">
<li>It does not include <code class="docutils literal notranslate"><span class="pre">~op=</span></code> operators yet.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">~op</span></code> behaves the same as <code class="docutils literal notranslate"><span class="pre">op</span></code> on lists, instead of raising
exceptions.</li>
</ul>
<p>These should be fixed when the final version of this proposal is ready.</p>
<ul>
<li>It reserves <code class="docutils literal notranslate"><span class="pre">xor</span></code> as an infix operator with the semantics equivalent to:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__xor__</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">b</span><span class="p">:</span> <span class="k">return</span> <span class="n">a</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="n">a</span><span class="p">:</span> <span class="k">return</span> <span class="n">b</span>
<span class="k">else</span><span class="p">:</span> <span class="mi">0</span>
</pre></div>
</div>
</li>
</ul>
<p>This preserves true value as much as possible, otherwise preserve left hand
side value if possible.</p>
<p>This is done so that bitwise operators could be regarded as elementwise
logical operators in the future (see below).</p>
</section>
<section id="alternatives-to-adding-new-operators">
<h2><a class="toc-backref" href="#alternatives-to-adding-new-operators" role="doc-backlink">Alternatives to adding new operators</a></h2>
<p>The discussions on comp.lang.python and python-dev mailing list explored many
alternatives. Some of the leading alternatives are listed here, using the
multiplication operator as an example.</p>
<ol class="arabic">
<li>Use function <code class="docutils literal notranslate"><span class="pre">mul(a,b)</span></code>.<p>Advantage:</p>
<ul class="simple">
<li>No need for new operators.</li>
</ul>
<p>Disadvantage:</p>
<ul class="simple">
<li>Prefix forms are cumbersome for composite formulas.</li>
<li>Unfamiliar to the intended users.</li>
<li>Too verbose for the intended users.</li>
<li>Unable to use natural precedence rules.</li>
</ul>
</li>
<li>Use method call <code class="docutils literal notranslate"><span class="pre">a.mul(b)</span></code>.<p>Advantage:</p>
<ul class="simple">
<li>No need for new operators.</li>
</ul>
<p>Disadvantage:</p>
<ul class="simple">
<li>Asymmetric for both operands.</li>
<li>Unfamiliar to the intended users.</li>
<li>Too verbose for the intended users.</li>
<li>Unable to use natural precedence rules.</li>
</ul>
</li>
<li>Use <em>shadow classes</em>. For matrix class define a shadow array class
accessible through a method <code class="docutils literal notranslate"><span class="pre">.E</span></code>, so that for matrices <em>a</em> and <em>b</em>,
<code class="docutils literal notranslate"><span class="pre">a.E*b</span></code> would be a matrix object that is <code class="docutils literal notranslate"><span class="pre">elementwise_mul(a,b)</span></code>.<p>Likewise define a shadow matrix class for arrays accessible through a method
<code class="docutils literal notranslate"><span class="pre">.M</span></code> so that for arrays <em>a</em> and <em>b</em>, <code class="docutils literal notranslate"><span class="pre">a.M*b</span></code> would be an array that is
<code class="docutils literal notranslate"><span class="pre">matrixwise_mul(a,b)</span></code>.</p>
<p>Advantage:</p>
<ul class="simple">
<li>No need for new operators.</li>
<li>Benefits of infix operators with correct precedence rules.</li>
<li>Clean formulas in applications.</li>
</ul>
<p>Disadvantage:</p>
<ul class="simple">
<li>Hard to maintain in current Python because ordinary numbers cannot have
user defined class methods; i.e. <code class="docutils literal notranslate"><span class="pre">a.E*b</span></code> will fail if a is a pure
number.</li>
<li>Difficult to implement, as this will interfere with existing method calls,
like <code class="docutils literal notranslate"><span class="pre">.T</span></code> for transpose, etc.</li>
<li>Runtime overhead of object creation and method lookup.</li>
<li>The shadowing class cannot replace a true class, because it does not
return its own type. So there need to be a <code class="docutils literal notranslate"><span class="pre">M</span></code> class with shadow <code class="docutils literal notranslate"><span class="pre">E</span></code>
class, and an <code class="docutils literal notranslate"><span class="pre">E</span></code> class with shadow <code class="docutils literal notranslate"><span class="pre">M</span></code> class.</li>
<li>Unnatural to mathematicians.</li>
</ul>
</li>
<li>Implement matrixwise and elementwise classes with easy casting to the other
class. So matrixwise operations for arrays would be like <code class="docutils literal notranslate"><span class="pre">a.M*b.M</span></code> and
elementwise operations for matrices would be like <code class="docutils literal notranslate"><span class="pre">a.E*b.E</span></code>. For error
detection <code class="docutils literal notranslate"><span class="pre">a.E*b.M</span></code> would raise exceptions.<p>Advantage:</p>
<ul class="simple">
<li>No need for new operators.</li>
<li>Similar to infix notation with correct precedence rules.</li>
</ul>
<p>Disadvantage:</p>
<ul class="simple">
<li>Similar difficulty due to lack of user-methods for pure numbers.</li>
<li>Runtime overhead of object creation and method lookup.</li>
<li>More cluttered formulas.</li>
<li>Switching of flavor of objects to facilitate operators becomes persistent.
This introduces long range context dependencies in application code that
would be extremely hard to maintain.</li>
</ul>
</li>
<li>Using mini parser to parse formulas written in arbitrary extension placed in
quoted strings.<p>Advantage:</p>
<ul class="simple">
<li>Pure Python, without new operators</li>
</ul>
<p>Disadvantage:</p>
<ul class="simple">
<li>The actual syntax is within the quoted string, which does not resolve the
problem itself.</li>
<li>Introducing zones of special syntax.</li>
<li>Demanding on the mini-parser.</li>
</ul>
</li>
<li>Introducing a single operator, such as <code class="docutils literal notranslate"><span class="pre">&#64;</span></code>, for matrix multiplication.<p>Advantage:</p>
<ul class="simple">
<li>Introduces less operators</li>
</ul>
<p>Disadvantage:</p>
<ul class="simple">
<li>The distinctions for operators like <code class="docutils literal notranslate"><span class="pre">+</span></code> <code class="docutils literal notranslate"><span class="pre">-</span></code> <code class="docutils literal notranslate"><span class="pre">**</span></code> are equally
important. Their meaning in matrix or array-oriented packages would be
reversed (see below).</li>
<li>The new operator occupies a special character.</li>
<li>This does not work well with more general object-element issues.</li>
</ul>
</li>
</ol>
<p>Among these alternatives, the first and second are used in current applications
to some extent, but found inadequate. The third is the most favorite for
applications, but it will incur huge implementation complexity. The fourth
would make applications codes very context-sensitive and hard to maintain.
These two alternatives also share significant implementational difficulties due
to current type/class split. The fifth appears to create more problems than it
would solve. The sixth does not cover the same range of applications.</p>
</section>
<section id="alternative-forms-of-infix-operators">
<h2><a class="toc-backref" href="#alternative-forms-of-infix-operators" role="doc-backlink">Alternative forms of infix operators</a></h2>
<p>Two major forms and several minor variants of new infix operators were
discussed:</p>
<ul>
<li>Bracketed form:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">op</span><span class="p">)</span>
<span class="p">[</span><span class="n">op</span><span class="p">]</span>
<span class="p">{</span><span class="n">op</span><span class="p">}</span>
<span class="o">&lt;</span><span class="n">op</span><span class="o">&gt;</span>
<span class="p">:</span><span class="n">op</span><span class="p">:</span>
<span class="o">~</span><span class="n">op</span><span class="o">~</span>
<span class="o">%</span><span class="n">op</span><span class="o">%</span>
</pre></div>
</div>
</li>
<li>Meta character form:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">.</span><span class="n">op</span>
<span class="nd">@op</span>
<span class="o">~</span><span class="n">op</span>
</pre></div>
</div>
<p>Alternatively the meta character is put after the operator.</p>
</li>
<li>Less consistent variations of these themes. These are considered
unfavorably. For completeness some are listed here:<ul class="simple">
<li>Use <code class="docutils literal notranslate"><span class="pre">&#64;/</span></code> and <code class="docutils literal notranslate"><span class="pre">/&#64;</span></code> for left and right division</li>
<li>Use <code class="docutils literal notranslate"><span class="pre">[*]</span></code> and <code class="docutils literal notranslate"><span class="pre">(*)</span></code> for outer and inner products</li>
<li>Use a single operator <code class="docutils literal notranslate"><span class="pre">&#64;</span></code> for multiplication.</li>
</ul>
</li>
<li>Use <code class="docutils literal notranslate"><span class="pre">__call__</span></code> to simulate multiplication:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">a</span><span class="p">)(</span><span class="n">b</span><span class="p">)</span>
</pre></div>
</div>
</li>
</ul>
<p>Criteria for choosing among the representations include:</p>
<ul class="simple">
<li>No syntactical ambiguities with existing operators.</li>
<li>Higher readability in actual formulas. This makes the bracketed forms
unfavorable. See examples below.</li>
<li>Visually similar to existing math operators.</li>
<li>Syntactically simple, without blocking possible future extensions.</li>
</ul>
<p>With these criteria the overall winner in bracket form appear to be <code class="docutils literal notranslate"><span class="pre">{op}</span></code>.
A clear winner in the meta character form is <code class="docutils literal notranslate"><span class="pre">~op</span></code>. Comparing these it
appears that <code class="docutils literal notranslate"><span class="pre">~op</span></code> is the favorite among them all.</p>
<p>Some analysis are as follows:</p>
<ul class="simple">
<li>The <code class="docutils literal notranslate"><span class="pre">.op</span></code> form is ambiguous: <code class="docutils literal notranslate"><span class="pre">1.+a</span></code> would be different from <code class="docutils literal notranslate"><span class="pre">1</span> <span class="pre">.+a</span></code>.</li>
<li>The bracket type operators are most favorable when standing alone, but
not in formulas, as they interfere with visual parsing of parentheses for
precedence and function argument. This is so for <code class="docutils literal notranslate"><span class="pre">(op)</span></code> and <code class="docutils literal notranslate"><span class="pre">[op]</span></code>, and
somewhat less so for <code class="docutils literal notranslate"><span class="pre">{op}</span></code> and <code class="docutils literal notranslate"><span class="pre">&lt;op&gt;</span></code>.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">&lt;op&gt;</span></code> form has the potential to be confused with <code class="docutils literal notranslate"><span class="pre">&lt;</span></code> <code class="docutils literal notranslate"><span class="pre">&gt;</span></code> and <code class="docutils literal notranslate"><span class="pre">=</span></code>.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">&#64;op</span></code> is not favored because <code class="docutils literal notranslate"><span class="pre">&#64;</span></code> is visually heavy (dense, more like
a letter): <code class="docutils literal notranslate"><span class="pre">a&#64;+b</span></code> is more readily read as <code class="docutils literal notranslate"><span class="pre">a&#64;</span> <span class="pre">+</span> <span class="pre">b</span></code> than <code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">&#64;+</span> <span class="pre">b</span></code>.</li>
<li>For choosing meta-characters: Most of existing ASCII symbols have already
been used. The only three unused are <code class="docutils literal notranslate"><span class="pre">&#64;</span></code> <code class="docutils literal notranslate"><span class="pre">$</span></code> <code class="docutils literal notranslate"><span class="pre">?</span></code>.</li>
</ul>
</section>
<section id="semantics-of-new-operators">
<h2><a class="toc-backref" href="#semantics-of-new-operators" role="doc-backlink">Semantics of new operators</a></h2>
<p>There are convincing arguments for using either set of operators as objectwise
or elementwise. Some of them are listed here:</p>
<ol class="arabic simple">
<li><code class="docutils literal notranslate"><span class="pre">op</span></code> for element, <code class="docutils literal notranslate"><span class="pre">~op</span></code> for object<ul class="simple">
<li>Consistent with current multiarray interface of Numeric package.</li>
<li>Consistent with some other languages.</li>
<li>Perception that elementwise operations are more natural.</li>
<li>Perception that elementwise operations are used more frequently</li>
</ul>
</li>
<li><code class="docutils literal notranslate"><span class="pre">op</span></code> for object, <code class="docutils literal notranslate"><span class="pre">~op</span></code> for element<ul class="simple">
<li>Consistent with current linear algebra interface of MatPy package.</li>
<li>Consistent with some other languages.</li>
<li>Perception that objectwise operations are more natural.</li>
<li>Perception that objectwise operations are used more frequently.</li>
<li>Consistent with the current behavior of operators on lists.</li>
<li>Allow <code class="docutils literal notranslate"><span class="pre">~</span></code> to be a general elementwise meta-character in future
extensions.</li>
</ul>
</li>
</ol>
<p>It is generally agreed upon that</p>
<ul class="simple">
<li>There is no absolute reason to favor one or the other.</li>
<li>It is easy to cast from one representation to another in a sizable chunk of
code, so the other flavor of operators is always minority.</li>
<li>There are other semantic differences that favor existence of array-oriented
and matrix-oriented packages, even if their operators are unified.</li>
<li>Whatever the decision is taken, codes using existing interfaces should not be
broken for a very long time.</li>
</ul>
<p>Therefore, not much is lost, and much flexibility retained, if the semantic
flavors of these two sets of operators are not dictated by the core language.
The application packages are responsible for making the most suitable choice.
This is already the case for NumPy and MatPy which use opposite semantics.
Adding new operators will not break this. See also observation after
subsection 2 in the Examples below.</p>
<p>The issue of numerical precision was raised, but if the semantics is left to
the applications, the actual precisions should also go there.</p>
</section>
<section id="examples">
<h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2>
<p>Following are examples of the actual formulas that will appear using various
operators or other representations described above.</p>
<ol class="arabic">
<li>The matrix inversion formula:<ul>
<li>Using <code class="docutils literal notranslate"><span class="pre">op</span></code> for object and <code class="docutils literal notranslate"><span class="pre">~op</span></code> for element:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">-</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">*</span> <span class="n">u</span> <span class="o">/</span> <span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">I</span> <span class="o">+</span> <span class="n">v</span><span class="o">/</span><span class="n">a</span><span class="o">*</span><span class="n">u</span><span class="p">)</span> <span class="o">*</span> <span class="n">v</span> <span class="o">/</span> <span class="n">a</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">-</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">*</span> <span class="n">u</span> <span class="o">*</span> <span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">I</span> <span class="o">+</span> <span class="n">v</span><span class="o">*</span><span class="n">a</span><span class="o">.</span><span class="n">I</span><span class="o">*</span><span class="n">u</span><span class="p">)</span><span class="o">.</span><span class="n">I</span> <span class="o">*</span> <span class="n">v</span> <span class="o">*</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span>
</pre></div>
</div>
</li>
<li>Using <code class="docutils literal notranslate"><span class="pre">op</span></code> for element and <code class="docutils literal notranslate"><span class="pre">~op</span></code> for object:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">@-</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">@*</span> <span class="n">u</span> <span class="o">@/</span> <span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">I</span> <span class="o">@+</span> <span class="n">v</span><span class="o">@/</span><span class="n">a</span><span class="o">@*</span><span class="n">u</span><span class="p">)</span> <span class="o">@*</span> <span class="n">v</span> <span class="o">@/</span> <span class="n">a</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">~-</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">~*</span> <span class="n">u</span> <span class="o">~/</span> <span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">I</span> <span class="o">~+</span> <span class="n">v</span><span class="o">~/</span><span class="n">a</span><span class="o">~*</span><span class="n">u</span><span class="p">)</span> <span class="o">~*</span> <span class="n">v</span> <span class="o">~/</span> <span class="n">a</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="p">(</span><span class="o">-</span><span class="p">)</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="p">(</span><span class="o">*</span><span class="p">)</span> <span class="n">u</span> <span class="p">(</span><span class="o">/</span><span class="p">)</span> <span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">I</span> <span class="p">(</span><span class="o">+</span><span class="p">)</span> <span class="n">v</span><span class="p">(</span><span class="o">/</span><span class="p">)</span><span class="n">a</span><span class="p">(</span><span class="o">*</span><span class="p">)</span><span class="n">u</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="p">)</span> <span class="n">v</span> <span class="p">(</span><span class="o">/</span><span class="p">)</span> <span class="n">a</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="p">[</span><span class="o">*</span><span class="p">]</span> <span class="n">u</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">I</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">v</span><span class="p">[</span><span class="o">/</span><span class="p">]</span><span class="n">a</span><span class="p">[</span><span class="o">*</span><span class="p">]</span><span class="n">u</span><span class="p">)</span> <span class="p">[</span><span class="o">*</span><span class="p">]</span> <span class="n">v</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">a</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">&lt;-&gt;</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">&lt;*&gt;</span> <span class="n">u</span> <span class="o">&lt;/&gt;</span> <span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">I</span> <span class="o">&lt;+&gt;</span> <span class="n">v</span><span class="o">&lt;/&gt;</span><span class="n">a</span><span class="o">&lt;*&gt;</span><span class="n">u</span><span class="p">)</span> <span class="o">&lt;*&gt;</span> <span class="n">v</span> <span class="o">&lt;/&gt;</span> <span class="n">a</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="p">{</span><span class="o">-</span><span class="p">}</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="p">{</span><span class="o">*</span><span class="p">}</span> <span class="n">u</span> <span class="p">{</span><span class="o">/</span><span class="p">}</span> <span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">I</span> <span class="p">{</span><span class="o">+</span><span class="p">}</span> <span class="n">v</span><span class="p">{</span><span class="o">/</span><span class="p">}</span><span class="n">a</span><span class="p">{</span><span class="o">*</span><span class="p">}</span><span class="n">u</span><span class="p">)</span> <span class="p">{</span><span class="o">*</span><span class="p">}</span> <span class="n">v</span> <span class="p">{</span><span class="o">/</span><span class="p">}</span> <span class="n">a</span>
</pre></div>
</div>
</li>
</ul>
<p>Observation: For linear algebra using <code class="docutils literal notranslate"><span class="pre">op</span></code> for object is preferable.</p>
<p>Observation: The <code class="docutils literal notranslate"><span class="pre">~op</span></code> type operators look better than <code class="docutils literal notranslate"><span class="pre">(op)</span></code> type in
complicated formulas.</p>
<ul>
<li>using named operators:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="nd">@sub</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="nd">@mul</span> <span class="n">u</span> <span class="nd">@div</span> <span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">I</span> <span class="nd">@add</span> <span class="n">v</span> <span class="nd">@div</span> <span class="n">a</span> <span class="nd">@mul</span> <span class="n">u</span><span class="p">)</span> <span class="nd">@mul</span> <span class="n">v</span> <span class="nd">@div</span> <span class="n">a</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">~</span><span class="n">sub</span> <span class="n">a</span><span class="o">.</span><span class="n">I</span> <span class="o">~</span><span class="n">mul</span> <span class="n">u</span> <span class="o">~</span><span class="n">div</span> <span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">I</span> <span class="o">~</span><span class="n">add</span> <span class="n">v</span> <span class="o">~</span><span class="n">div</span> <span class="n">a</span> <span class="o">~</span><span class="n">mul</span> <span class="n">u</span><span class="p">)</span> <span class="o">~</span><span class="n">mul</span> <span class="n">v</span> <span class="o">~</span><span class="n">div</span> <span class="n">a</span>
</pre></div>
</div>
</li>
</ul>
<p>Observation: Named operators are not suitable for math formulas.</p>
</li>
<li>Plotting a 3d graph<ul>
<li>Using <code class="docutils literal notranslate"><span class="pre">op</span></code> for object and <code class="docutils literal notranslate"><span class="pre">~op</span></code> for element:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">z</span> <span class="o">=</span> <span class="n">sin</span><span class="p">(</span><span class="n">x</span><span class="o">~**</span><span class="mi">2</span> <span class="o">~+</span> <span class="n">y</span><span class="o">~**</span><span class="mi">2</span><span class="p">);</span> <span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">,</span><span class="n">z</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li>Using op for element and ~op for object:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">z</span> <span class="o">=</span> <span class="n">sin</span><span class="p">(</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">y</span><span class="o">**</span><span class="mi">2</span><span class="p">);</span> <span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">,</span><span class="n">z</span><span class="p">)</span>
</pre></div>
</div>
</li>
</ul>
<p>Observation: Elementwise operations with broadcasting allows much more
efficient implementation than MatLab.</p>
<p>Observation: It is useful to have two related classes with the semantics of
<code class="docutils literal notranslate"><span class="pre">op</span></code> and <code class="docutils literal notranslate"><span class="pre">~op</span></code> swapped. Using these the <code class="docutils literal notranslate"><span class="pre">~op</span></code> operators would only
need to appear in chunks of code where the other flavor dominates, while
maintaining consistent semantics of the code.</p>
</li>
<li>Using <code class="docutils literal notranslate"><span class="pre">+</span></code> and <code class="docutils literal notranslate"><span class="pre">-</span></code> with automatic broadcasting:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="n">b</span> <span class="o">-</span> <span class="n">c</span><span class="p">;</span> <span class="n">d</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">T</span><span class="o">*</span><span class="n">a</span>
</pre></div>
</div>
<p>Observation: This would silently produce hard-to-trace bugs if one of <em>b</em> or
<em>c</em> is row vector while the other is column vector.</p>
</li>
</ol>
</section>
<section id="miscellaneous-issues">
<h2><a class="toc-backref" href="#miscellaneous-issues" role="doc-backlink">Miscellaneous issues</a></h2>
<ul>
<li>Need for the <code class="docutils literal notranslate"><span class="pre">~+</span></code> <code class="docutils literal notranslate"><span class="pre">~-</span></code> operators. The objectwise <code class="docutils literal notranslate"><span class="pre">+</span></code> <code class="docutils literal notranslate"><span class="pre">-</span></code> are
important because they provide important sanity checks as per linear algebra.
The elementwise <code class="docutils literal notranslate"><span class="pre">+</span></code> <code class="docutils literal notranslate"><span class="pre">-</span></code> are important because they allow broadcasting
that are very efficient in applications.</li>
<li>Left division (solve). For matrix, <code class="docutils literal notranslate"><span class="pre">a*x</span></code> is not necessarily equal to
<code class="docutils literal notranslate"><span class="pre">x*a</span></code>. The solution of <code class="docutils literal notranslate"><span class="pre">a*x==b</span></code>, denoted <code class="docutils literal notranslate"><span class="pre">x=solve(a,b)</span></code>, is therefore
different from the solution of <code class="docutils literal notranslate"><span class="pre">x*a==b</span></code>, denoted <code class="docutils literal notranslate"><span class="pre">x=div(b,a)</span></code>. There are
discussions about finding a new symbol for solve. [Background: MatLab use
<code class="docutils literal notranslate"><span class="pre">b/a</span></code> for <code class="docutils literal notranslate"><span class="pre">div(b,a)</span></code> and <code class="docutils literal notranslate"><span class="pre">a\b</span></code> for <code class="docutils literal notranslate"><span class="pre">solve(a,b)</span></code>.]<p>It is recognized that Python provides a better solution without requiring a
new symbol: the <code class="docutils literal notranslate"><span class="pre">inverse</span></code> method <code class="docutils literal notranslate"><span class="pre">.I</span></code> can be made to be delayed so that
<code class="docutils literal notranslate"><span class="pre">a.I*b</span></code> and <code class="docutils literal notranslate"><span class="pre">b*a.I</span></code> are equivalent to Matlabs <code class="docutils literal notranslate"><span class="pre">a\b</span></code> and <code class="docutils literal notranslate"><span class="pre">b/a</span></code>. The
implementation is quite simple and the resulting application code clean.</p>
</li>
<li>Power operator. Pythons use of <code class="docutils literal notranslate"><span class="pre">a**b</span></code> as <code class="docutils literal notranslate"><span class="pre">pow(a,b)</span></code> has two perceived
disadvantages:<ul class="simple">
<li>Most mathematicians are more familiar with <code class="docutils literal notranslate"><span class="pre">a^b</span></code> for this purpose.</li>
<li>It results in long augmented assignment operator <code class="docutils literal notranslate"><span class="pre">~**=</span></code>.</li>
</ul>
<p>However, this issue is distinct from the main issue here.</p>
</li>
<li>Additional multiplication operators. Several forms of multiplications are
used in (multi-)linear algebra. Most can be seen as variations of
multiplication in linear algebra sense (such as Kronecker product). But two
forms appear to be more fundamental: outer product and inner product.
However, their specification includes indices, which can be either<ul class="simple">
<li>associated with the operator, or</li>
<li>associated with the objects.</li>
</ul>
<p>The latter (the Einstein notation) is used extensively on paper, and is also
the easier one to implement. By implementing a tensor-with-indices class, a
general form of multiplication would cover both outer and inner products, and
specialize to linear algebra multiplication as well. The index rule can be
defined as class methods, like:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="n">b</span><span class="o">.</span><span class="n">i</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="n">c</span><span class="o">.</span><span class="n">i</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># a_ijkl = b_ijmn c_lnkm</span>
</pre></div>
</div>
<p>Therefore, one objectwise multiplication is sufficient.</p>
</li>
<li>Bitwise operators.<ul class="simple">
<li>The proposed new math operators use the symbol ~ that is <em>bitwise not</em>
operator. This poses no compatibility problem but somewhat complicates
implementation.</li>
<li>The symbol <code class="docutils literal notranslate"><span class="pre">^</span></code> might be better used for <code class="docutils literal notranslate"><span class="pre">pow</span></code> than bitwise <code class="docutils literal notranslate"><span class="pre">xor</span></code>. But
this depends on the future of bitwise operators. It does not immediately
impact on the proposed math operator.</li>
<li>The symbol <code class="docutils literal notranslate"><span class="pre">|</span></code> was suggested to be used for matrix solve. But the new
solution of using delayed <code class="docutils literal notranslate"><span class="pre">.I</span></code> is better in several ways.</li>
<li>The current proposal fits in a larger and more general extension that will
remove the need for special bitwise operators. (See elementization below.)</li>
</ul>
</li>
<li>Alternative to special operator names used in definition,<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="s2">&quot;+&quot;</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span> <span class="ow">in</span> <span class="n">place</span> <span class="n">of</span> <span class="k">def</span> <span class="fm">__add__</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
</pre></div>
</div>
<p>This appears to require greater syntactical change, and would only be useful
when arbitrary additional operators are allowed.</p>
</li>
</ul>
</section>
<section id="impact-on-general-elementization">
<h2><a class="toc-backref" href="#impact-on-general-elementization" role="doc-backlink">Impact on general elementization</a></h2>
<p>The distinction between objectwise and elementwise operations are meaningful in
other contexts as well, where an object can be conceptually regarded as a
collection of elements. It is important that the current proposal does not
preclude possible future extensions.</p>
<p>One general future extension is to use <code class="docutils literal notranslate"><span class="pre">~</span></code> as a meta operator to <em>elementize</em>
a given operator. Several examples are listed here:</p>
<ol class="arabic">
<li>Bitwise operators. Currently Python assigns six operators to bitwise
operations: and (<code class="docutils literal notranslate"><span class="pre">&amp;</span></code>), or (<code class="docutils literal notranslate"><span class="pre">|</span></code>), xor (<code class="docutils literal notranslate"><span class="pre">^</span></code>), complement (<code class="docutils literal notranslate"><span class="pre">~</span></code>), left
shift (<code class="docutils literal notranslate"><span class="pre">&lt;&lt;</span></code>) and right shift (<code class="docutils literal notranslate"><span class="pre">&gt;&gt;</span></code>), with their own precedence levels.<p>Among them, the <code class="docutils literal notranslate"><span class="pre">&amp;</span></code> <code class="docutils literal notranslate"><span class="pre">|</span></code> <code class="docutils literal notranslate"><span class="pre">^</span></code> <code class="docutils literal notranslate"><span class="pre">~</span></code> operators can be regarded as
elementwise versions of lattice operators applied to integers regarded as
bit strings.:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">5</span> <span class="ow">and</span> <span class="mi">6</span> <span class="c1"># 6</span>
<span class="mi">5</span> <span class="ow">or</span> <span class="mi">6</span> <span class="c1"># 5</span>
<span class="mi">5</span> <span class="o">~</span><span class="ow">and</span> <span class="mi">6</span> <span class="c1"># 4</span>
<span class="mi">5</span> <span class="o">~</span><span class="ow">or</span> <span class="mi">6</span> <span class="c1"># 7</span>
</pre></div>
</div>
<p>These can be regarded as general elementwise lattice operators, not
restricted to bits in integers.</p>
<p>In order to have named operators for <code class="docutils literal notranslate"><span class="pre">xor</span></code> <code class="docutils literal notranslate"><span class="pre">~xor</span></code>, it is necessary to
make <code class="docutils literal notranslate"><span class="pre">xor</span></code> a reserved word.</p>
</li>
<li>List arithmetics.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span> <span class="c1"># [1, 2, 3, 4]</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span> <span class="o">~+</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span> <span class="c1"># [4, 6]</span>
<span class="p">[</span><span class="s1">&#39;a&#39;</span><span class="p">,</span> <span class="s1">&#39;b&#39;</span><span class="p">]</span> <span class="o">*</span> <span class="mi">2</span> <span class="c1"># [&#39;a&#39;, &#39;b&#39;, &#39;a&#39;, &#39;b&#39;]</span>
<span class="s1">&#39;ab&#39;</span> <span class="o">*</span> <span class="mi">2</span> <span class="c1"># &#39;abab&#39;</span>
<span class="p">[</span><span class="s1">&#39;a&#39;</span><span class="p">,</span> <span class="s1">&#39;b&#39;</span><span class="p">]</span> <span class="o">~*</span> <span class="mi">2</span> <span class="c1"># [&#39;aa&#39;, &#39;bb&#39;]</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span> <span class="o">~*</span> <span class="mi">2</span> <span class="c1"># [2, 4]</span>
</pre></div>
</div>
<p>It is also consistent to Cartesian product:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span><span class="o">*</span><span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span> <span class="c1"># [(1,3),(1,4),(2,3),(2,4)]</span>
</pre></div>
</div>
</li>
<li>List comprehension.:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">];</span> <span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
<span class="o">~</span><span class="n">f</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">)</span> <span class="c1"># [f(x,y) for x, y in zip(a,b)]</span>
<span class="o">~</span><span class="n">f</span><span class="p">(</span><span class="n">a</span><span class="o">*</span><span class="n">b</span><span class="p">)</span> <span class="c1"># [f(x,y) for x in a for y in b]</span>
<span class="n">a</span> <span class="o">~+</span> <span class="n">b</span> <span class="c1"># [x + y for x, y in zip(a,b)]</span>
</pre></div>
</div>
</li>
<li>Tuple generation (the zip function in Python 2.0):<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">]</span> <span class="c1"># ([1,2, 3], [4, 5, 6])</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span><span class="o">~</span><span class="p">,[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">]</span> <span class="c1"># [(1,4), (2, 5), (3,6)]</span>
</pre></div>
</div>
</li>
<li>Using <code class="docutils literal notranslate"><span class="pre">~</span></code> as generic elementwise meta-character to replace map:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">~</span><span class="n">f</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span> <span class="c1"># map(f, a, b)</span>
<span class="o">~~</span><span class="n">f</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span> <span class="c1"># map(lambda *x:map(f, *x), a, b)</span>
</pre></div>
</div>
<p>More generally,:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="o">~</span><span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">x</span><span class="p">):</span> <span class="k">return</span> <span class="nb">map</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="o">*</span><span class="n">x</span><span class="p">)</span>
<span class="k">def</span> <span class="o">~~</span><span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">x</span><span class="p">):</span> <span class="k">return</span> <span class="nb">map</span><span class="p">(</span><span class="o">~</span><span class="n">f</span><span class="p">,</span> <span class="o">*</span><span class="n">x</span><span class="p">)</span>
<span class="o">...</span>
</pre></div>
</div>
</li>
<li>Elementwise format operator (with broadcasting):<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span>
<span class="nb">print</span> <span class="p">[</span><span class="s2">&quot;</span><span class="si">%5d</span><span class="s2"> &quot;</span><span class="p">]</span> <span class="o">~%</span> <span class="n">a</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]]</span>
<span class="nb">print</span> <span class="p">[</span><span class="s2">&quot;</span><span class="si">%5d</span><span class="s2"> &quot;</span><span class="p">]</span> <span class="o">~~%</span> <span class="n">a</span>
</pre></div>
</div>
</li>
<li>Rich comparison:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span> <span class="o">~&lt;</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="c1"># [1, 0, 0]</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span> <span class="o">~==</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="c1"># [0, 1, 0]</span>
</pre></div>
</div>
</li>
<li>Rich indexing:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">]</span> <span class="o">~</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="c1"># [c, d, b]</span>
</pre></div>
</div>
</li>
<li>Tuple flattening:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span> <span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
<span class="n">f</span><span class="p">(</span><span class="o">~</span><span class="n">a</span><span class="p">,</span> <span class="o">~</span><span class="n">b</span><span class="p">)</span> <span class="c1"># f(1,2,3,4)</span>
</pre></div>
</div>
</li>
<li>Copy operator:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">~=</span> <span class="n">b</span> <span class="c1"># a = b.copy()</span>
</pre></div>
</div>
</li>
</ol>
<blockquote>
<div>There can be specific levels of deep copy:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">~~=</span> <span class="n">b</span> <span class="c1"># a = b.copy(2)</span>
</pre></div>
</div>
</div></blockquote>
<section id="notes">
<h3><a class="toc-backref" href="#notes" role="doc-backlink">Notes</a></h3>
<ol class="arabic simple">
<li>There are probably many other similar situations. This general approach
seems well suited for most of them, in place of several separated extensions
for each of them (parallel and cross iteration, list comprehension, rich
comparison, etc).</li>
<li>The semantics of <em>elementwise</em> depends on applications. For example, an
element of matrix is two levels down from the list-of-list point of view.
This requires more fundamental change than the current proposal. In any
case, the current proposal will not negatively impact on future
possibilities of this nature.</li>
</ol>
<p>Note that this section describes a type of future extensions that is consistent
with current proposal, but may present additional compatibility or other
problems. They are not tied to the current proposal.</p>
</section>
</section>
<section id="impact-on-named-operators">
<h2><a class="toc-backref" href="#impact-on-named-operators" role="doc-backlink">Impact on named operators</a></h2>
<p>The discussions made it generally clear that infix operators is a scarce
resource in Python, not only in numerical computation, but in other fields as
well. Several proposals and ideas were put forward that would allow infix
operators be introduced in ways similar to named functions. We show here that
the current extension does not negatively impact on future extensions in this
regard.</p>
<ol class="arabic">
<li>Named infix operators.<p>Choose a meta character, say <code class="docutils literal notranslate"><span class="pre">&#64;</span></code>, so that for any identifier <code class="docutils literal notranslate"><span class="pre">opname</span></code>,
the combination <code class="docutils literal notranslate"><span class="pre">&#64;opname</span></code> would be a binary infix operator, and:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="nd">@opname</span> <span class="n">b</span> <span class="o">==</span> <span class="n">opname</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">)</span>
</pre></div>
</div>
<p>Other representations mentioned include:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">.</span><span class="n">name</span> <span class="o">~</span><span class="n">name</span><span class="o">~</span> <span class="p">:</span><span class="n">name</span><span class="p">:</span> <span class="p">(</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="o">%</span><span class="n">name</span><span class="o">%</span>
</pre></div>
</div>
<p>and similar variations. The pure bracket based operators cannot be used
this way.</p>
<p>This requires a change in the parser to recognize <code class="docutils literal notranslate"><span class="pre">&#64;opname</span></code>, and parse it
into the same structure as a function call. The precedence of all these
operators would have to be fixed at one level, so the implementation would
be different from additional math operators which keep the precedence of
existing math operators.</p>
<p>The current proposed extension do not limit possible future extensions of
such form in any way.</p>
</li>
<li>More general symbolic operators.<p>One additional form of future extension is to use meta character and
operator symbols (symbols that cannot be used in syntactical structures
other than operators). Suppose <code class="docutils literal notranslate"><span class="pre">&#64;</span></code> is the meta character. Then:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span> <span class="o">@+</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span> <span class="o">@@+</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span> <span class="o">@+-</span> <span class="n">b</span>
</pre></div>
</div>
<p>would all be operators with a hierarchy of precedence, defined by:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="s2">&quot;+&quot;</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="k">def</span> <span class="s2">&quot;@+&quot;</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="k">def</span> <span class="s2">&quot;@@+&quot;</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="k">def</span> <span class="s2">&quot;@+-&quot;</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
</pre></div>
</div>
<p>One advantage compared with named operators is greater flexibility for
precedences based on either the meta character or the ordinary operator
symbols. This also allows operator composition. The disadvantage is that
they are more like <em>line noise</em>. In any case the current proposal does not
impact its future possibility.</p>
<p>These kinds of future extensions may not be necessary when Unicode becomes
generally available.</p>
<p>Note that this section discusses compatibility of the proposed extension
with possible future extensions. The desirability or compatibility of these
other extensions themselves are specifically not considered here.</p>
</li>
</ol>
</section>
<section id="credits-and-archives">
<h2><a class="toc-backref" href="#credits-and-archives" role="doc-backlink">Credits and archives</a></h2>
<p>The discussions mostly happened in July to August of 2000 on news group
comp.lang.python and the mailing list python-dev. There are altogether several
hundred postings, most can be retrieved from these two pages (and searching
word “operator”):</p>
<blockquote>
<div><a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/">http://www.python.org/pipermail/python-list/2000-July/</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-August/">http://www.python.org/pipermail/python-list/2000-August/</a></div></blockquote>
<p>The names of contributors are too numerous to mention here, suffice to say that
a large proportion of ideas discussed here are not our own.</p>
<p>Several key postings (from our point of view) that may help to navigate the
discussions include:</p>
<blockquote>
<div><a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/108893.html">http://www.python.org/pipermail/python-list/2000-July/108893.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/108777.html">http://www.python.org/pipermail/python-list/2000-July/108777.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/108848.html">http://www.python.org/pipermail/python-list/2000-July/108848.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/109237.html">http://www.python.org/pipermail/python-list/2000-July/109237.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/109250.html">http://www.python.org/pipermail/python-list/2000-July/109250.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/109310.html">http://www.python.org/pipermail/python-list/2000-July/109310.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/109448.html">http://www.python.org/pipermail/python-list/2000-July/109448.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/109491.html">http://www.python.org/pipermail/python-list/2000-July/109491.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/109537.html">http://www.python.org/pipermail/python-list/2000-July/109537.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/109607.html">http://www.python.org/pipermail/python-list/2000-July/109607.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/109709.html">http://www.python.org/pipermail/python-list/2000-July/109709.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/109804.html">http://www.python.org/pipermail/python-list/2000-July/109804.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/109857.html">http://www.python.org/pipermail/python-list/2000-July/109857.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/110061.html">http://www.python.org/pipermail/python-list/2000-July/110061.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-July/110208.html">http://www.python.org/pipermail/python-list/2000-July/110208.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-August/111427.html">http://www.python.org/pipermail/python-list/2000-August/111427.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-August/111558.html">http://www.python.org/pipermail/python-list/2000-August/111558.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-August/112551.html">http://www.python.org/pipermail/python-list/2000-August/112551.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-August/112606.html">http://www.python.org/pipermail/python-list/2000-August/112606.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-August/112758.html">http://www.python.org/pipermail/python-list/2000-August/112758.html</a><p><a class="reference external" href="http://www.python.org/pipermail/python-dev/2000-July/013243.html">http://www.python.org/pipermail/python-dev/2000-July/013243.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-dev/2000-July/013364.html">http://www.python.org/pipermail/python-dev/2000-July/013364.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-dev/2000-August/014940.html">http://www.python.org/pipermail/python-dev/2000-August/014940.html</a></p>
</div></blockquote>
<p>These are earlier drafts of this PEP:</p>
<blockquote>
<div><a class="reference external" href="http://www.python.org/pipermail/python-list/2000-August/111785.html">http://www.python.org/pipermail/python-list/2000-August/111785.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-list/2000-August/112529.html">http://www.python.org/pipermail/python-list/2000-August/112529.html</a>
<a class="reference external" href="http://www.python.org/pipermail/python-dev/2000-August/014906.html">http://www.python.org/pipermail/python-dev/2000-August/014906.html</a></div></blockquote>
<p>There is an alternative PEP (officially, <a class="pep reference internal" href="../pep-0211/" title="PEP 211 Adding A New Outer Product Operator">PEP 211</a>) by Greg Wilson, titled
“Adding New Linear Algebra Operators to Python”.</p>
<p>Its first (and current) version is at:</p>
<blockquote>
<div><a class="reference external" href="http://www.python.org/pipermail/python-dev/2000-August/014876.html">http://www.python.org/pipermail/python-dev/2000-August/014876.html</a>
<a class="pep reference internal" href="../pep-0211/" title="PEP 211 Adding A New Outer Product Operator">PEP 211</a></div></blockquote>
</section>
<section id="additional-references">
<h2><a class="toc-backref" href="#additional-references" role="doc-backlink">Additional References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://MatPy.sourceforge.net/Misc/index.html">http://MatPy.sourceforge.net/Misc/index.html</a></aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0225.rst">https://github.com/python/peps/blob/main/peps/pep-0225.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0225.rst">2024-04-14 20:08:31 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#proposed-extension">Proposed extension</a></li>
<li><a class="reference internal" href="#prototype-implementation">Prototype Implementation</a></li>
<li><a class="reference internal" href="#alternatives-to-adding-new-operators">Alternatives to adding new operators</a></li>
<li><a class="reference internal" href="#alternative-forms-of-infix-operators">Alternative forms of infix operators</a></li>
<li><a class="reference internal" href="#semantics-of-new-operators">Semantics of new operators</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#miscellaneous-issues">Miscellaneous issues</a></li>
<li><a class="reference internal" href="#impact-on-general-elementization">Impact on general elementization</a><ul>
<li><a class="reference internal" href="#notes">Notes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#impact-on-named-operators">Impact on named operators</a></li>
<li><a class="reference internal" href="#credits-and-archives">Credits and archives</a></li>
<li><a class="reference internal" href="#additional-references">Additional References</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0225.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

226
pep-0226/index.html Normal file
View File

@ -0,0 +1,226 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 226 Python 2.1 Release Schedule | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0226/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 226 Python 2.1 Release Schedule | peps.python.org'>
<meta property="og:description" content="This document describes the post Python 2.0 development and release schedule. According to this schedule, Python 2.1 will be released in April of 2001. The schedule primarily concerns itself with PEP-size items. Small bug fixes and changes will occur...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0226/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This document describes the post Python 2.0 development and release schedule. According to this schedule, Python 2.1 will be released in April of 2001. The schedule primarily concerns itself with PEP-size items. Small bug fixes and changes will occur...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 226</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 226 Python 2.1 Release Schedule</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Jeremy Hylton &lt;jeremy&#32;&#97;t&#32;alum.mit.edu&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Topic<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../topic/release/">Release</a></dd>
<dt class="field-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">16-Oct-2000</dd>
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
<dd class="field-even">2.1</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#release-schedule">Release Schedule</a></li>
<li><a class="reference internal" href="#open-issues-for-python-2-0-beta-2">Open issues for Python 2.0 beta 2</a></li>
<li><a class="reference internal" href="#guidelines-for-making-changes-for-python-2-1">Guidelines for making changes for Python 2.1</a></li>
<li><a class="reference internal" href="#general-guidelines-for-submitting-patches-and-making-changes">General guidelines for submitting patches and making changes</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This document describes the post Python 2.0 development and
release schedule. According to this schedule, Python 2.1 will be
released in April of 2001. The schedule primarily concerns
itself with PEP-size items. Small bug fixes and changes will
occur up until the first beta release.</p>
</section>
<section id="release-schedule">
<h2><a class="toc-backref" href="#release-schedule" role="doc-backlink">Release Schedule</a></h2>
<p>Tentative future release dates</p>
<p>[bugfix release dates go here]</p>
<p>Past release dates:</p>
<ul class="simple">
<li>17-Apr-2001: 2.1 final release</li>
<li>15-Apr-2001: 2.1 release candidate 2</li>
<li>13-Apr-2001: 2.1 release candidate 1</li>
<li>23-Mar-2001: Python 2.1 beta 2 release</li>
<li>02-Mar-2001: First 2.1 beta release</li>
<li>02-Feb-2001: Python 2.1 alpha 2 release</li>
<li>22-Jan-2001: Python 2.1 alpha 1 release</li>
<li>16-Oct-2000: Python 2.0 final release</li>
</ul>
</section>
<section id="open-issues-for-python-2-0-beta-2">
<h2><a class="toc-backref" href="#open-issues-for-python-2-0-beta-2" role="doc-backlink">Open issues for Python 2.0 beta 2</a></h2>
<p>Add a default unit testing framework to the standard library.</p>
</section>
<section id="guidelines-for-making-changes-for-python-2-1">
<h2><a class="toc-backref" href="#guidelines-for-making-changes-for-python-2-1" role="doc-backlink">Guidelines for making changes for Python 2.1</a></h2>
<p>The guidelines and schedule will be revised based on discussion in
the <a class="reference external" href="mailto:python-dev&#37;&#52;&#48;python&#46;org">python-dev<span>&#64;</span>python<span>&#46;</span>org</a> mailing list.</p>
<p>The PEP system was instituted late in the Python 2.0 development
cycle and many changes did not follow the process described in <a class="pep reference internal" href="../pep-0001/" title="PEP 1 PEP Purpose and Guidelines">PEP 1</a>.
The development process for 2.1, however, will follow the PEP
process as documented.</p>
<p>The first eight weeks following 2.0 final will be the design and
review phase. By the end of this period, any PEP that is proposed
for 2.1 should be ready for review. This means that the PEP is
written and discussion has occurred on the <a class="reference external" href="mailto:python-dev&#37;&#52;&#48;python&#46;org">python-dev<span>&#64;</span>python<span>&#46;</span>org</a>
and <a class="reference external" href="mailto:python-list&#37;&#52;&#48;python&#46;org">python-list<span>&#64;</span>python<span>&#46;</span>org</a> mailing lists.</p>
<p>The next six weeks will be spent reviewing the PEPs and
implementing and testing the accepted PEPs. When this period
stops, we will end consideration of any incomplete PEPs. Near the
end of this period, there will be a feature freeze where any small
features not worthy of a PEP will not be accepted.</p>
<p>Before the final release, we will have six weeks of beta testing
and a release candidate or two.</p>
</section>
<section id="general-guidelines-for-submitting-patches-and-making-changes">
<h2><a class="toc-backref" href="#general-guidelines-for-submitting-patches-and-making-changes" role="doc-backlink">General guidelines for submitting patches and making changes</a></h2>
<p>Use good sense when committing changes. You should know what we
mean by good sense or we wouldnt have given you commit privileges
&lt;0.5 wink&gt;. Some specific examples of good sense include:</p>
<ul class="simple">
<li>Do whatever the dictator tells you.</li>
<li>Discuss any controversial changes on python-dev first. If you
get a lot of +1 votes and no -1 votes, make the change. If you
get a some -1 votes, think twice; consider asking Guido what he
thinks.</li>
<li>If the change is to code you contributed, it probably makes
sense for you to fix it.</li>
<li>If the change affects code someone else wrote, it probably makes
sense to ask him or her first.</li>
<li>You can use the SourceForge (SF) Patch Manager to submit a patch
and assign it to someone for review.</li>
</ul>
<p>Any significant new feature must be described in a PEP and
approved before it is checked in.</p>
<p>Any significant code addition, such as a new module or large
patch, must include test cases for the regression test and
documentation. A patch should not be checked in until the tests
and documentation are ready.</p>
<p>If you fix a bug, you should write a test case that would have
caught the bug.</p>
<p>If you commit a patch from the SF Patch Manager or fix a bug from
the Jitterbug database, be sure to reference the patch/bug number
in the CVS log message. Also be sure to change the status in the
patch manager or bug database (if you have access to the bug
database).</p>
<p>It is not acceptable for any checked in code to cause the
regression test to fail. If a checkin causes a failure, it must
be fixed within 24 hours or it will be backed out.</p>
<p>All contributed C code must be ANSI C. If possible check it with
two different compilers, e.g. gcc and MSVC.</p>
<p>All contributed Python code must follow Guidos Python style
guide. <a class="reference external" href="http://www.python.org/doc/essays/styleguide.html">http://www.python.org/doc/essays/styleguide.html</a></p>
<p>It is understood that any code contributed will be released under
an Open Source license. Do not contribute code if it cant be
released this way.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0226.rst">https://github.com/python/peps/blob/main/peps/pep-0226.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0226.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#release-schedule">Release Schedule</a></li>
<li><a class="reference internal" href="#open-issues-for-python-2-0-beta-2">Open issues for Python 2.0 beta 2</a></li>
<li><a class="reference internal" href="#guidelines-for-making-changes-for-python-2-1">Guidelines for making changes for Python 2.1</a></li>
<li><a class="reference internal" href="#general-guidelines-for-submitting-patches-and-making-changes">General guidelines for submitting patches and making changes</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0226.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

602
pep-0227/index.html Normal file
View File

@ -0,0 +1,602 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 227 Statically Nested Scopes | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0227/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 227 Statically Nested Scopes | peps.python.org'>
<meta property="og:description" content="This PEP describes the addition of statically nested scoping (lexical scoping) for Python 2.2, and as a source level option for python 2.1. In addition, Python 2.1 will issue warnings about constructs whose meaning may change when this feature is enabled.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0227/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes the addition of statically nested scoping (lexical scoping) for Python 2.2, and as a source level option for python 2.1. In addition, Python 2.1 will issue warnings about constructs whose meaning may change when this feature is enabled.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 227</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 227 Statically Nested Scopes</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Jeremy Hylton &lt;jeremy&#32;&#97;t&#32;alum.mit.edu&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">01-Nov-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#specification">Specification</a></li>
<li><a class="reference internal" href="#discussion">Discussion</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards compatibility</a></li>
<li><a class="reference internal" href="#compatibility-of-c-api">Compatibility of C API</a></li>
<li><a class="reference internal" href="#locals-vars">locals() / vars()</a></li>
<li><a class="reference internal" href="#warnings-and-errors">Warnings and Errors</a><ul>
<li><a class="reference internal" href="#import-used-in-function-scope">import * used in function scope</a></li>
<li><a class="reference internal" href="#bare-exec-in-function-scope">bare exec in function scope</a></li>
<li><a class="reference internal" href="#local-shadows-global">local shadows global</a></li>
<li><a class="reference internal" href="#rebinding-names-in-enclosing-scopes">Rebinding names in enclosing scopes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP describes the addition of statically nested scoping
(lexical scoping) for Python 2.2, and as a source level option
for python 2.1. In addition, Python 2.1 will issue warnings about
constructs whose meaning may change when this feature is enabled.</p>
<p>The old language definition (2.0 and before) defines exactly three
namespaces that are used to resolve names the local, global,
and built-in namespaces. The addition of nested scopes allows
resolution of unbound local names in enclosing functions
namespaces.</p>
<p>The most visible consequence of this change is that lambdas (and
other nested functions) can reference variables defined in the
surrounding namespace. Currently, lambdas must often use default
arguments to explicitly creating bindings in the lambdas
namespace.</p>
</section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This proposal changes the rules for resolving free variables in
Python functions. The new name resolution semantics will take
effect with Python 2.2. These semantics will also be available in
Python 2.1 by adding “from __future__ import nested_scopes” to the
top of a module. (See <a class="pep reference internal" href="../pep-0236/" title="PEP 236 Back to the __future__">PEP 236</a>.)</p>
<p>The Python 2.0 definition specifies exactly three namespaces to
check for each name the local namespace, the global namespace,
and the builtin namespace. According to this definition, if a
function A is defined within a function B, the names bound in B
are not visible in A. The proposal changes the rules so that
names bound in B are visible in A (unless A contains a name
binding that hides the binding in B).</p>
<p>This specification introduces rules for lexical scoping that are
common in Algol-like languages. The combination of lexical
scoping and existing support for first-class functions is
reminiscent of Scheme.</p>
<p>The changed scoping rules address two problems the limited
utility of lambda expressions (and nested functions in general),
and the frequent confusion of new users familiar with other
languages that support nested lexical scopes, e.g. the inability
to define recursive functions except at the module level.</p>
<p>The lambda expression yields an unnamed function that evaluates a
single expression. It is often used for callback functions. In
the example below (written using the Python 2.0 rules), any name
used in the body of the lambda must be explicitly passed as a
default argument to the lambda.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">Tkinter</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">Tk</span><span class="p">()</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="s2">&quot;Click here&quot;</span><span class="p">,</span>
<span class="n">command</span><span class="o">=</span><span class="k">lambda</span> <span class="n">root</span><span class="o">=</span><span class="n">root</span><span class="p">:</span> <span class="n">root</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">configure</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="s2">&quot;...&quot;</span><span class="p">))</span>
</pre></div>
</div>
<p>This approach is cumbersome, particularly when there are several
names used in the body of the lambda. The long list of default
arguments obscures the purpose of the code. The proposed
solution, in crude terms, implements the default argument approach
automatically. The “root=root” argument can be omitted.</p>
<p>The new name resolution semantics will cause some programs to
behave differently than they did under Python 2.0. In some cases,
programs will fail to compile. In other cases, names that were
previously resolved using the global namespace will be resolved
using the local namespace of an enclosing function. In Python
2.1, warnings will be issued for all statements that will behave
differently.</p>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>Python is a statically scoped language with block structure, in
the traditional of Algol. A code block or region, such as a
module, class definition, or function body, is the basic unit of a
program.</p>
<p>Names refer to objects. Names are introduced by name binding
operations. Each occurrence of a name in the program text refers
to the binding of that name established in the innermost function
block containing the use.</p>
<p>The name binding operations are argument declaration, assignment,
class and function definition, import statements, for statements,
and except clauses. Each name binding occurs within a block
defined by a class or function definition or at the module level
(the top-level code block).</p>
<p>If a name is bound anywhere within a code block, all uses of the
name within the block are treated as references to the current
block. (Note: This can lead to errors when a name is used within
a block before it is bound.)</p>
<p>If the global statement occurs within a block, all uses of the
name specified in the statement refer to the binding of that name
in the top-level namespace. Names are resolved in the top-level
namespace by searching the global namespace, i.e. the namespace of
the module containing the code block, and in the builtin
namespace, i.e. the namespace of the <code class="docutils literal notranslate"><span class="pre">__builtin__</span></code> module. The
global namespace is searched first. If the name is not found
there, the builtin namespace is searched. The global statement
must precede all uses of the name.</p>
<p>If a name is used within a code block, but it is not bound there
and is not declared global, the use is treated as a reference to
the nearest enclosing function region. (Note: If a region is
contained within a class definition, the name bindings that occur
in the class block are not visible to enclosed functions.)</p>
<p>A class definition is an executable statement that may contain
uses and definitions of names. These references follow the normal
rules for name resolution. The namespace of the class definition
becomes the attribute dictionary of the class.</p>
<p>The following operations are name binding operations. If they
occur within a block, they introduce new local names in the
current block unless there is also a global declaration.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Function</span> <span class="n">definition</span><span class="p">:</span> <span class="k">def</span> <span class="nf">name</span> <span class="o">...</span>
<span class="n">Argument</span> <span class="n">declaration</span><span class="p">:</span> <span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="o">...</span><span class="n">name</span><span class="o">...</span><span class="p">),</span> <span class="k">lambda</span> <span class="o">...</span><span class="n">name</span><span class="o">...</span>
<span class="n">Class</span> <span class="n">definition</span><span class="p">:</span> <span class="k">class</span> <span class="nc">name</span> <span class="o">...</span>
<span class="n">Assignment</span> <span class="n">statement</span><span class="p">:</span> <span class="n">name</span> <span class="o">=</span> <span class="o">...</span>
<span class="n">Import</span> <span class="n">statement</span><span class="p">:</span> <span class="kn">import</span> <span class="nn">name</span><span class="o">,</span> <span class="nn">import</span> <span class="n">module</span> <span class="k">as</span> <span class="n">name</span><span class="p">,</span>
<span class="kn">from</span> <span class="nn">module</span> <span class="kn">import</span> <span class="n">name</span>
<span class="n">Implicit</span> <span class="n">assignment</span><span class="p">:</span> <span class="n">names</span> <span class="n">are</span> <span class="n">bound</span> <span class="n">by</span> <span class="k">for</span> <span class="n">statements</span> <span class="ow">and</span> <span class="k">except</span>
<span class="n">clauses</span>
</pre></div>
</div>
<p>There are several cases where Python statements are illegal when
used in conjunction with nested scopes that contain free
variables.</p>
<p>If a variable is referenced in an enclosed scope, it is an error
to delete the name. The compiler will raise a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code> for
del name.</p>
<p>If the wild card form of import (<code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">*</span></code>) is used in a function
and the function contains a nested block with free variables, the
compiler will raise a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code>.</p>
<p>If exec is used in a function and the function contains a nested
block with free variables, the compiler will raise a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code>
unless the exec explicitly specifies the local namespace for the
exec. (In other words, “exec obj” would be illegal, but
“exec obj in ns” would be legal.)</p>
<p>If a name bound in a function scope is also the name of a module
global name or a standard builtin name, and the function contains
a nested function scope that references the name, the compiler
will issue a warning. The name resolution rules will result in
different bindings under Python 2.0 than under Python 2.2. The
warning indicates that the program may not run correctly with all
versions of Python.</p>
</section>
<section id="discussion">
<h2><a class="toc-backref" href="#discussion" role="doc-backlink">Discussion</a></h2>
<p>The specified rules allow names defined in a function to be
referenced in any nested function defined with that function. The
name resolution rules are typical for statically scoped languages,
with three primary exceptions:</p>
<ul class="simple">
<li>Names in class scope are not accessible.</li>
<li>The global statement short-circuits the normal rules.</li>
<li>Variables are not declared.</li>
</ul>
<p>Names in class scope are not accessible. Names are resolved in
the innermost enclosing function scope. If a class definition
occurs in a chain of nested scopes, the resolution process skips
class definitions. This rule prevents odd interactions between
class attributes and local variable access. If a name binding
operation occurs in a class definition, it creates an attribute on
the resulting class object. To access this variable in a method,
or in a function nested within a method, an attribute reference
must be used, either via self or via the class name.</p>
<p>An alternative would have been to allow name binding in class
scope to behave exactly like name binding in function scope. This
rule would allow class attributes to be referenced either via
attribute reference or simple name. This option was ruled out
because it would have been inconsistent with all other forms of
class and instance attribute access, which always use attribute
references. Code that used simple names would have been obscure.</p>
<p>The global statement short-circuits the normal rules. Under the
proposal, the global statement has exactly the same effect that it
does for Python 2.0. It is also noteworthy because it allows name
binding operations performed in one block to change bindings in
another block (the module).</p>
<p>Variables are not declared. If a name binding operation occurs
anywhere in a function, then that name is treated as local to the
function and all references refer to the local binding. If a
reference occurs before the name is bound, a NameError is raised.
The only kind of declaration is the global statement, which allows
programs to be written using mutable global variables. As a
consequence, it is not possible to rebind a name defined in an
enclosing scope. An assignment operation can only bind a name in
the current scope or in the global scope. The lack of
declarations and the inability to rebind names in enclosing scopes
are unusual for lexically scoped languages; there is typically a
mechanism to create name bindings (e.g. lambda and let in Scheme)
and a mechanism to change the bindings (set! in Scheme).</p>
</section>
<section id="examples">
<h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2>
<p>A few examples are included to illustrate the way the rules work.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">make_adder</span><span class="p">(</span><span class="n">base</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">adder</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">base</span> <span class="o">+</span> <span class="n">x</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">adder</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">add5</span> <span class="o">=</span> <span class="n">make_adder</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">add5</span><span class="p">(</span><span class="mi">6</span><span class="p">)</span>
<span class="go">11</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">make_fact</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">fact</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">return</span> <span class="mi">1</span><span class="n">L</span>
<span class="gp">... </span> <span class="k">else</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="n">fact</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">fact</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fact</span> <span class="o">=</span> <span class="n">make_fact</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fact</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span>
<span class="go">5040L</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">make_wrapper</span><span class="p">(</span><span class="n">obj</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">class</span> <span class="nc">Wrapper</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">def</span> <span class="fm">__getattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">attr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">&#39;_&#39;</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">attr</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">else</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">,</span> <span class="n">attr</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">Wrapper</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">Test</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">public</span> <span class="o">=</span> <span class="mi">2</span>
<span class="gp">... </span> <span class="n">_private</span> <span class="o">=</span> <span class="mi">3</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">w</span> <span class="o">=</span> <span class="n">make_wrapper</span><span class="p">(</span><span class="n">Test</span><span class="p">())</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">w</span><span class="o">.</span><span class="n">public</span>
<span class="go">2</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">w</span><span class="o">.</span><span class="n">_private</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">?</span>
<span class="gr">AttributeError</span>: <span class="n">_private</span>
</pre></div>
</div>
<p>An example from Tim Peters demonstrates the potential pitfalls of
nested scopes in the absence of declarations:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">i</span> <span class="o">=</span> <span class="mi">6</span>
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">g</span><span class="p">():</span>
<span class="nb">print</span> <span class="n">i</span>
<span class="c1"># ...</span>
<span class="c1"># skip to the next page</span>
<span class="c1"># ...</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span> <span class="c1"># ah, i *is* local to f, so this is what g sees</span>
<span class="k">pass</span>
<span class="n">g</span><span class="p">()</span>
</pre></div>
</div>
<p>The call to <code class="docutils literal notranslate"><span class="pre">g()</span></code> will refer to the variable i bound in <code class="docutils literal notranslate"><span class="pre">f()</span></code> by the for
loop. If <code class="docutils literal notranslate"><span class="pre">g()</span></code> is called before the loop is executed, a NameError will
be raised.</p>
</section>
<section id="backwards-compatibility">
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards compatibility</a></h2>
<p>There are two kinds of compatibility problems caused by nested
scopes. In one case, code that behaved one way in earlier
versions behaves differently because of nested scopes. In the
other cases, certain constructs interact badly with nested scopes
and will trigger SyntaxErrors at compile time.</p>
<p>The following example from Skip Montanaro illustrates the first
kind of problem:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">def</span> <span class="nf">f1</span><span class="p">():</span>
<span class="n">x</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">def</span> <span class="nf">inner</span><span class="p">():</span>
<span class="nb">print</span> <span class="n">x</span>
<span class="n">inner</span><span class="p">()</span>
</pre></div>
</div>
<p>Under the Python 2.0 rules, the print statement inside <code class="docutils literal notranslate"><span class="pre">inner()</span></code>
refers to the global variable x and will print 1 if <code class="docutils literal notranslate"><span class="pre">f1()</span></code> is
called. Under the new rules, it refers to the <code class="docutils literal notranslate"><span class="pre">f1()</span></code>s namespace,
the nearest enclosing scope with a binding.</p>
<p>The problem occurs only when a global variable and a local
variable share the same name and a nested function uses that name
to refer to the global variable. This is poor programming
practice, because readers will easily confuse the two different
variables. One example of this problem was found in the Python
standard library during the implementation of nested scopes.</p>
<p>To address this problem, which is unlikely to occur often, the
Python 2.1 compiler (when nested scopes are not enabled) issues a
warning.</p>
<p>The other compatibility problem is caused by the use of <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">*</span></code>
and exec in a function body, when that function contains a
nested scope and the contained scope has free variables. For
example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">y</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">def</span> <span class="nf">f</span><span class="p">():</span>
<span class="n">exec</span> <span class="s2">&quot;y = &#39;gotcha&#39;&quot;</span> <span class="c1"># or from module import *</span>
<span class="k">def</span> <span class="nf">g</span><span class="p">():</span>
<span class="k">return</span> <span class="n">y</span>
<span class="o">...</span>
</pre></div>
</div>
<p>At compile-time, the compiler cannot tell whether an exec that
operates on the local namespace or an <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">*</span></code> will introduce
name bindings that shadow the global y. Thus, it is not possible
to tell whether the reference to y in <code class="docutils literal notranslate"><span class="pre">g()</span></code> should refer to the
global or to a local name in <code class="docutils literal notranslate"><span class="pre">f()</span></code>.</p>
<p>In discussion of the python-list, people argued for both possible
interpretations. On the one hand, some thought that the reference
in <code class="docutils literal notranslate"><span class="pre">g()</span></code> should be bound to a local y if one exists. One problem
with this interpretation is that it is impossible for a human
reader of the code to determine the binding of y by local
inspection. It seems likely to introduce subtle bugs. The other
interpretation is to treat exec and import * as dynamic features
that do not effect static scoping. Under this interpretation, the
exec and import * would introduce local names, but those names
would never be visible to nested scopes. In the specific example
above, the code would behave exactly as it did in earlier versions
of Python.</p>
<p>Since each interpretation is problematic and the exact meaning
ambiguous, the compiler raises an exception. The Python 2.1
compiler issues a warning when nested scopes are not enabled.</p>
<p>A brief review of three Python projects (the standard library,
Zope, and a beta version of PyXPCOM) found four backwards
compatibility issues in approximately 200,000 lines of code.
There was one example of case #1 (subtle behavior change) and two
examples of <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">*</span></code> problems in the standard library.</p>
<p>(The interpretation of the <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">*</span></code> and exec restriction that was
implemented in Python 2.1a2 was much more restrictive, based on
language that in the reference manual that had never been
enforced. These restrictions were relaxed following the release.)</p>
</section>
<section id="compatibility-of-c-api">
<h2><a class="toc-backref" href="#compatibility-of-c-api" role="doc-backlink">Compatibility of C API</a></h2>
<p>The implementation causes several Python C API functions to
change, including <code class="docutils literal notranslate"><span class="pre">PyCode_New()</span></code>. As a result, C extensions may
need to be updated to work correctly with Python 2.1.</p>
</section>
<section id="locals-vars">
<h2><a class="toc-backref" href="#locals-vars" role="doc-backlink">locals() / vars()</a></h2>
<p>These functions return a dictionary containing the current scopes
local variables. Modifications to the dictionary do not affect
the values of variables. Under the current rules, the use of
<code class="docutils literal notranslate"><span class="pre">locals()</span></code> and <code class="docutils literal notranslate"><span class="pre">globals()</span></code> allows the program to gain access to all
the namespaces in which names are resolved.</p>
<p>An analogous function will not be provided for nested scopes.
Under this proposal, it will not be possible to gain
dictionary-style access to all visible scopes.</p>
</section>
<section id="warnings-and-errors">
<h2><a class="toc-backref" href="#warnings-and-errors" role="doc-backlink">Warnings and Errors</a></h2>
<p>The compiler will issue warnings in Python 2.1 to help identify
programs that may not compile or run correctly under future
versions of Python. Under Python 2.2 or Python 2.1 if the
<code class="docutils literal notranslate"><span class="pre">nested_scopes</span></code> future statement is used, which are collectively
referred to as “future semantics” in this section, the compiler
will issue SyntaxErrors in some cases.</p>
<p>The warnings typically apply when a function that contains a
nested function that has free variables. For example, if function
F contains a function G and G uses the builtin <code class="docutils literal notranslate"><span class="pre">len()</span></code>, then F is a
function that contains a nested function (G) with a free variable
(len). The label “free-in-nested” will be used to describe these
functions.</p>
<section id="import-used-in-function-scope">
<h3><a class="toc-backref" href="#import-used-in-function-scope" role="doc-backlink">import * used in function scope</a></h3>
<p>The language reference specifies that <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">*</span></code> may only occur
in a module scope. (Sec. 6.11) The implementation of C
Python has supported <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">*</span></code> at the function scope.</p>
<p>If <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">*</span></code> is used in the body of a free-in-nested function,
the compiler will issue a warning. Under future semantics,
the compiler will raise a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code>.</p>
</section>
<section id="bare-exec-in-function-scope">
<h3><a class="toc-backref" href="#bare-exec-in-function-scope" role="doc-backlink">bare exec in function scope</a></h3>
<p>The exec statement allows two optional expressions following
the keyword “in” that specify the namespaces used for locals
and globals. An exec statement that omits both of these
namespaces is a bare exec.</p>
<p>If a bare exec is used in the body of a free-in-nested
function, the compiler will issue a warning. Under future
semantics, the compiler will raise a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code>.</p>
</section>
<section id="local-shadows-global">
<h3><a class="toc-backref" href="#local-shadows-global" role="doc-backlink">local shadows global</a></h3>
<p>If a free-in-nested function has a binding for a local
variable that (1) is used in a nested function and (2) is the
same as a global variable, the compiler will issue a warning.</p>
</section>
<section id="rebinding-names-in-enclosing-scopes">
<h3><a class="toc-backref" href="#rebinding-names-in-enclosing-scopes" role="doc-backlink">Rebinding names in enclosing scopes</a></h3>
<p>There are technical issues that make it difficult to support
rebinding of names in enclosing scopes, but the primary reason
that it is not allowed in the current proposal is that Guido is
opposed to it. His motivation: it is difficult to support,
because it would require a new mechanism that would allow the
programmer to specify that an assignment in a block is supposed to
rebind the name in an enclosing block; presumably a keyword or
special syntax (x := 3) would make this possible. Given that this
would encourage the use of local variables to hold state that is
better stored in a class instance, its not worth adding new
syntax to make this possible (in Guidos opinion).</p>
<p>The proposed rules allow programmers to achieve the effect of
rebinding, albeit awkwardly. The name that will be effectively
rebound by enclosed functions is bound to a container object. In
place of assignment, the program uses modification of the
container to achieve the desired effect:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">bank_account</span><span class="p">(</span><span class="n">initial_balance</span><span class="p">):</span>
<span class="n">balance</span> <span class="o">=</span> <span class="p">[</span><span class="n">initial_balance</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">deposit</span><span class="p">(</span><span class="n">amount</span><span class="p">):</span>
<span class="n">balance</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">balance</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">amount</span>
<span class="k">return</span> <span class="n">balance</span>
<span class="k">def</span> <span class="nf">withdraw</span><span class="p">(</span><span class="n">amount</span><span class="p">):</span>
<span class="n">balance</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">balance</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">amount</span>
<span class="k">return</span> <span class="n">balance</span>
<span class="k">return</span> <span class="n">deposit</span><span class="p">,</span> <span class="n">withdraw</span>
</pre></div>
</div>
<p>Support for rebinding in nested scopes would make this code
clearer. A class that defines <code class="docutils literal notranslate"><span class="pre">deposit()</span></code> and <code class="docutils literal notranslate"><span class="pre">withdraw()</span></code> methods
and the balance as an instance variable would be clearer still.
Since classes seem to achieve the same effect in a more
straightforward manner, they are preferred.</p>
</section>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>The implementation for C Python uses flat closures <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>. Each def
or lambda expression that is executed will create a closure if the
body of the function or any contained function has free
variables. Using flat closures, the creation of closures is
somewhat expensive but lookup is cheap.</p>
<p>The implementation adds several new opcodes and two new kinds of
names in code objects. A variable can be either a cell variable
or a free variable for a particular code object. A cell variable
is referenced by containing scopes; as a result, the function
where it is defined must allocate separate storage for it on each
invocation. A free variable is referenced via a functions
closure.</p>
<p>The choice of free closures was made based on three factors.
First, nested functions are presumed to be used infrequently,
deeply nested (several levels of nesting) still less frequently.
Second, lookup of names in a nested scope should be fast.
Third, the use of nested scopes, particularly where a function
that access an enclosing scope is returned, should not prevent
unreferenced objects from being reclaimed by the garbage
collector.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd>Luca Cardelli. Compiling a functional language. In Proc. of
the 1984 ACM Conference on Lisp and Functional Programming,
pp. 208-217, Aug. 1984
<a class="reference external" href="https://dl.acm.org/doi/10.1145/800055.802037">https://dl.acm.org/doi/10.1145/800055.802037</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0227.rst">https://github.com/python/peps/blob/main/peps/pep-0227.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0227.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#specification">Specification</a></li>
<li><a class="reference internal" href="#discussion">Discussion</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards compatibility</a></li>
<li><a class="reference internal" href="#compatibility-of-c-api">Compatibility of C API</a></li>
<li><a class="reference internal" href="#locals-vars">locals() / vars()</a></li>
<li><a class="reference internal" href="#warnings-and-errors">Warnings and Errors</a><ul>
<li><a class="reference internal" href="#import-used-in-function-scope">import * used in function scope</a></li>
<li><a class="reference internal" href="#bare-exec-in-function-scope">bare exec in function scope</a></li>
<li><a class="reference internal" href="#local-shadows-global">local shadows global</a></li>
<li><a class="reference internal" href="#rebinding-names-in-enclosing-scopes">Rebinding names in enclosing scopes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0227.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

252
pep-0228/index.html Normal file
View File

@ -0,0 +1,252 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 228 Reworking Pythons Numeric Model | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0228/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 228 Reworking Pythons Numeric Model | peps.python.org'>
<meta property="og:description" content="Today, Pythons numerical model is similar to the C numeric model: there are several unrelated numerical types, and when operations between numerical types are requested, coercions happen. While the C rationale for the numerical model is that it is ver...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0228/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Today, Pythons numerical model is similar to the C numeric model: there are several unrelated numerical types, and when operations between numerical types are requested, coercions happen. While the C rationale for the numerical model is that it is ver...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 228</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 228 Reworking Pythons Numeric Model</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Moshe Zadka &lt;moshez&#32;&#97;t&#32;zadka.site.co.il&gt;, Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">04-Nov-2000</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#withdrawal">Withdrawal</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#other-numerical-models">Other Numerical Models</a></li>
<li><a class="reference internal" href="#suggested-interface-for-python-s-numerical-model">Suggested Interface For Pythons Numerical Model</a></li>
<li><a class="reference internal" href="#coercion">Coercion</a></li>
<li><a class="reference internal" href="#inexact-operations">Inexact Operations</a></li>
<li><a class="reference internal" href="#numerical-python-issues">Numerical Python Issues</a></li>
<li><a class="reference internal" href="#unresolved-issues">Unresolved Issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="withdrawal">
<h2><a class="toc-backref" href="#withdrawal" role="doc-backlink">Withdrawal</a></h2>
<p>This PEP has been withdrawn in favor of <a class="pep reference internal" href="../pep-3141/" title="PEP 3141 A Type Hierarchy for Numbers">PEP 3141</a>.</p>
</section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Today, Pythons numerical model is similar to the C numeric model:
there are several unrelated numerical types, and when operations
between numerical types are requested, coercions happen. While
the C rationale for the numerical model is that it is very similar
to what happens at the hardware level, that rationale does not
apply to Python. So, while it is acceptable to C programmers that
<code class="docutils literal notranslate"><span class="pre">2/3</span> <span class="pre">==</span> <span class="pre">0</span></code>, it is surprising to many Python programmers.</p>
<p>NOTE: in the light of recent discussions in the newsgroup, the
motivation in this PEP (and details) need to be extended.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>In usability studies, one of the least usable aspect of Python was
the fact that integer division returns the floor of the division.
This makes it hard to program correctly, requiring casts to
<code class="docutils literal notranslate"><span class="pre">float()</span></code> in various parts through the code. Pythons numerical
model stems from C, while a model that might be easier to work with
can be based on the mathematical understanding of numbers.</p>
</section>
<section id="other-numerical-models">
<h2><a class="toc-backref" href="#other-numerical-models" role="doc-backlink">Other Numerical Models</a></h2>
<p>Perls numerical model is that there is one type of numbers
floating point numbers. While it is consistent and superficially
non-surprising, it tends to have subtle gotchas. One of these is
that printing numbers is very tricky, and requires correct
rounding. In Perl, there is also a mode where all numbers are
integers. This mode also has its share of problems, which arise
from the fact that there is not even an approximate way of
dividing numbers and getting meaningful answers.</p>
</section>
<section id="suggested-interface-for-python-s-numerical-model">
<h2><a class="toc-backref" href="#suggested-interface-for-python-s-numerical-model" role="doc-backlink">Suggested Interface For Pythons Numerical Model</a></h2>
<p>While coercion rules will remain for add-on types and classes, the
built in type system will have exactly one Python type a
number. There are several things which can be considered “number
methods”:</p>
<ol class="arabic simple">
<li><code class="docutils literal notranslate"><span class="pre">isnatural()</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">isintegral()</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">isrational()</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">isreal()</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">iscomplex()</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">isexact()</span></code></li>
</ol>
<p>Obviously, a number which answers true to a question from 1 to 5, will
also answer true to any following question. If <code class="docutils literal notranslate"><span class="pre">isexact()</span></code> is not true,
then any answer might be wrong.
(But not horribly wrong: its close to the truth.)</p>
<p>Now, there is two thing the models promises for the field operations
(<code class="docutils literal notranslate"><span class="pre">+</span></code>, <code class="docutils literal notranslate"><span class="pre">-</span></code>, <code class="docutils literal notranslate"><span class="pre">/</span></code>, <code class="docutils literal notranslate"><span class="pre">*</span></code>):</p>
<ul class="simple">
<li>If both operands satisfy <code class="docutils literal notranslate"><span class="pre">isexact()</span></code>, the result satisfies
<code class="docutils literal notranslate"><span class="pre">isexact()</span></code>.</li>
<li>All field rules are true, except that for not-<code class="docutils literal notranslate"><span class="pre">isexact()</span></code> numbers,
they might be only approximately true.</li>
</ul>
<p>One consequence of these two rules is that all exact calculations
are done as (complex) rationals: since the field laws must hold,
then</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a</span><span class="o">/</span><span class="n">b</span><span class="p">)</span><span class="o">*</span><span class="n">b</span> <span class="o">==</span> <span class="n">a</span>
</pre></div>
</div>
<p>must hold.</p>
<p>There is built-in function, <code class="docutils literal notranslate"><span class="pre">inexact()</span></code> which takes a number
and returns an inexact number which is a good approximation.
Inexact numbers must be as least as accurate as if they were
using IEEE-754.</p>
<p>Several of the classical Python functions will return exact numbers
even when given inexact numbers: e.g, <code class="docutils literal notranslate"><span class="pre">int()</span></code>.</p>
</section>
<section id="coercion">
<h2><a class="toc-backref" href="#coercion" role="doc-backlink">Coercion</a></h2>
<p>The number type does not define <code class="docutils literal notranslate"><span class="pre">nb_coerce</span></code>
Any numeric operation slot, when receiving something other then <code class="docutils literal notranslate"><span class="pre">PyNumber</span></code>,
refuses to implement it.</p>
</section>
<section id="inexact-operations">
<h2><a class="toc-backref" href="#inexact-operations" role="doc-backlink">Inexact Operations</a></h2>
<p>The functions in the <code class="docutils literal notranslate"><span class="pre">math</span></code> module will be allowed to return
inexact results for exact values. However, they will never return
a non-real number. The functions in the <code class="docutils literal notranslate"><span class="pre">cmath</span></code> module are also
allowed to return an inexact result for an exact argument, and are
furthermore allowed to return a complex result for a real
argument.</p>
</section>
<section id="numerical-python-issues">
<h2><a class="toc-backref" href="#numerical-python-issues" role="doc-backlink">Numerical Python Issues</a></h2>
<p>People who use Numerical Python do so for high-performance vector
operations. Therefore, NumPy should keep its hardware based
numeric model.</p>
</section>
<section id="unresolved-issues">
<h2><a class="toc-backref" href="#unresolved-issues" role="doc-backlink">Unresolved Issues</a></h2>
<p>Which number literals will be exact, and which inexact?</p>
<p>How do we deal with IEEE 754 operations? (probably, isnan/isinf should
be methods)</p>
<p>On 64-bit machines, comparisons between ints and floats may be
broken when the comparison involves conversion to float. Ditto
for comparisons between longs and floats. This can be dealt with
by avoiding the conversion to float. (Due to Andrew Koenig.)</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0228.rst">https://github.com/python/peps/blob/main/peps/pep-0228.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0228.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#withdrawal">Withdrawal</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#other-numerical-models">Other Numerical Models</a></li>
<li><a class="reference internal" href="#suggested-interface-for-python-s-numerical-model">Suggested Interface For Pythons Numerical Model</a></li>
<li><a class="reference internal" href="#coercion">Coercion</a></li>
<li><a class="reference internal" href="#inexact-operations">Inexact Operations</a></li>
<li><a class="reference internal" href="#numerical-python-issues">Numerical Python Issues</a></li>
<li><a class="reference internal" href="#unresolved-issues">Unresolved Issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0228.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

220
pep-0229/index.html Normal file
View File

@ -0,0 +1,220 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 229 Using Distutils to Build Python | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0229/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 229 Using Distutils to Build Python | peps.python.org'>
<meta property="og:description" content="The Modules/Setup mechanism has some flaws:">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0229/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="The Modules/Setup mechanism has some flaws:">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 229</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 229 Using Distutils to Build Python</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">A.M. Kuchling &lt;amk&#32;&#97;t&#32;amk.ca&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">16-Nov-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#unresolved-issues">Unresolved Issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">Modules/Setup</span></code> mechanism has some flaws:</p>
<ul class="simple">
<li>People have to remember to uncomment bits of <code class="docutils literal notranslate"><span class="pre">Modules/Setup</span></code> in
order to get all the possible modules.</li>
<li>Moving <code class="docutils literal notranslate"><span class="pre">Setup</span></code> to a new version of Python is tedious; new modules
have been added, so you cant just copy the older version, but
have to reconcile the two versions.</li>
<li>Users have to figure out where the needed libraries, such as
<code class="docutils literal notranslate"><span class="pre">zlib</span></code>, are installed.</li>
</ul>
</section>
<section id="proposal">
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
<p>Use the Distutils to build the modules that come with Python.</p>
<p>The changes can be broken up into several pieces:</p>
<ol class="arabic">
<li>The Distutils needs some Python modules to be able to build
modules. Currently I believe the minimal list is <code class="docutils literal notranslate"><span class="pre">posix</span></code>, <code class="docutils literal notranslate"><span class="pre">_sre</span></code>,
and <code class="docutils literal notranslate"><span class="pre">string</span></code>.<p>These modules will have to be built before the Distutils can be
used, so theyll simply be hardwired into <code class="docutils literal notranslate"><span class="pre">Modules/Makefile</span></code> and
be automatically built.</p>
</li>
<li>A top-level setup.py script will be written that checks the
libraries installed on the system and compiles as many modules
as possible.</li>
<li><code class="docutils literal notranslate"><span class="pre">Modules/Setup</span></code> will be kept and settings in it will override
<code class="docutils literal notranslate"><span class="pre">setup.py</span></code>s usual behavior, so you can disable a module known
to be buggy, or specify particular compilation or linker flags.
However, in the common case where <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> works correctly,
everything in <code class="docutils literal notranslate"><span class="pre">Setup</span></code> will remain commented out. The other
<code class="docutils literal notranslate"><span class="pre">Setup.*</span></code> become unnecessary, since nothing will be generating
<code class="docutils literal notranslate"><span class="pre">Setup</span></code> automatically.</li>
</ol>
<p>The patch was checked in for Python 2.1, and has been subsequently
modified.</p>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>Patch #102588 on SourceForge contains the proposed patch.
Currently the patch tries to be conservative and to change as few
files as possible, in order to simplify backing out the patch.
For example, no attempt is made to rip out the existing build
mechanisms. Such simplifications can wait for later in the beta
cycle, when were certain the patch will be left in, or they can
wait for Python 2.2.</p>
<p>The patch makes the following changes:</p>
<ul class="simple">
<li>Makes some required changes to distutils/sysconfig (these will
be checked in separately)</li>
<li>In the top-level <code class="docutils literal notranslate"><span class="pre">Makefile.in</span></code>, the “sharedmods” target simply
runs <code class="docutils literal notranslate"><span class="pre">&quot;./python</span> <span class="pre">setup.py</span> <span class="pre">build&quot;</span></code>, and “sharedinstall” runs
<code class="docutils literal notranslate"><span class="pre">&quot;./python</span> <span class="pre">setup.py</span> <span class="pre">install&quot;</span></code>. The “clobber” target also deletes
the <code class="docutils literal notranslate"><span class="pre">build/</span></code> subdirectory where Distutils puts its output.</li>
<li><code class="docutils literal notranslate"><span class="pre">Modules/Setup.config.in</span></code> only contains entries for the <code class="docutils literal notranslate"><span class="pre">gc</span></code> and <code class="docutils literal notranslate"><span class="pre">thread</span></code>
modules; the <code class="docutils literal notranslate"><span class="pre">readline</span></code>, <code class="docutils literal notranslate"><span class="pre">curses</span></code>, and <code class="docutils literal notranslate"><span class="pre">db</span></code> modules are removed because
its now <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>s job to handle them.</li>
<li><code class="docutils literal notranslate"><span class="pre">Modules/Setup.dist</span></code> now contains entries for only 3 modules
<code class="docutils literal notranslate"><span class="pre">_sre</span></code>, <code class="docutils literal notranslate"><span class="pre">posix</span></code>, and <code class="docutils literal notranslate"><span class="pre">strop</span></code>.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">configure</span></code> script builds <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code> from <code class="docutils literal notranslate"><span class="pre">setup.cfg.in</span></code>. This
is needed for two reasons: to make building in subdirectories
work, and to get the configured installation prefix.</li>
<li>Adds <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> to the top directory of the source tree. <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>
is the largest piece of the puzzle, though not the most
complicated. <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> contains a subclass of the <code class="docutils literal notranslate"><span class="pre">BuildExt</span></code>
class, and extends it with a <code class="docutils literal notranslate"><span class="pre">detect_modules()</span></code> method that does
the work of figuring out when modules can be compiled, and adding
them to the exts list.</li>
</ul>
</section>
<section id="unresolved-issues">
<h2><a class="toc-backref" href="#unresolved-issues" role="doc-backlink">Unresolved Issues</a></h2>
<p>Do we need to make it possible to disable the 3 hard-wired modules
without manually hacking the Makefiles? [Answer: No.]</p>
<p>The Distutils always compile modules as shared libraries. How do
we support compiling them statically into the resulting Python
binary?</p>
<p>[Answer: building a Python binary with the Distutils should be
feasible, though no one has implemented it yet. This should be
done someday, but isnt a pressing priority as messing around with
the top-level <code class="docutils literal notranslate"><span class="pre">Makefile.pre.in</span></code> is good enough.]</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0229.rst">https://github.com/python/peps/blob/main/peps/pep-0229.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0229.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#unresolved-issues">Unresolved Issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0229.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

454
pep-0230/index.html Normal file
View File

@ -0,0 +1,454 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 230 Warning Framework | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0230/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 230 Warning Framework | peps.python.org'>
<meta property="og:description" content="This PEP proposes a C and Python level API, as well as command line flags, to issue warning messages and control what happens to them. This is mostly based on GvRs proposal posted to python-dev on 05-Nov-2000, with some ideas (such as using classes to...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0230/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP proposes a C and Python level API, as well as command line flags, to issue warning messages and control what happens to them. This is mostly based on GvRs proposal posted to python-dev on 05-Nov-2000, with some ideas (such as using classes to...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 230</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 230 Warning Framework</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">28-Nov-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">05-Nov-2000</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#apis-for-issuing-warnings">APIs For Issuing Warnings</a></li>
<li><a class="reference internal" href="#warnings-categories">Warnings Categories</a></li>
<li><a class="reference internal" href="#the-warnings-filter">The Warnings Filter</a></li>
<li><a class="reference internal" href="#warnings-output-and-formatting-hooks">Warnings Output And Formatting Hooks</a></li>
<li><a class="reference internal" href="#api-for-manipulating-warning-filters">API For Manipulating Warning Filters</a></li>
<li><a class="reference internal" href="#command-line-syntax">Command Line Syntax</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#rejected-concerns">Rejected Concerns</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP proposes a C and Python level API, as well as command
line flags, to issue warning messages and control what happens to
them. This is mostly based on GvRs proposal posted to python-dev
on 05-Nov-2000, with some ideas (such as using classes to
categorize warnings) merged in from Paul Prescods
counter-proposal posted on the same date. Also, an attempt to
implement the proposal caused several small tweaks.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>With Python 3000 looming, it is necessary to start issuing
warnings about the use of obsolete or deprecated features, in
addition to errors. There are also lots of other reasons to be
able to issue warnings, both from C and from Python code, both at
compile time and at run time.</p>
<p>Warnings arent fatal, and thus its possible that a program
triggers the same warning many times during a single execution.
It would be annoying if a program emitted an endless stream of
identical warnings. Therefore, a mechanism is needed that
suppresses multiple identical warnings.</p>
<p>It is also desirable to have user control over which warnings are
printed. While in general it is useful to see all warnings all
the time, there may be times where it is impractical to fix the
code right away in a production program. In this case, there
should be a way to suppress warnings.</p>
<p>It is also useful to be able to suppress specific warnings during
program development, e.g. when a warning is generated by a piece
of 3rd party code that cannot be fixed right away, or when there
is no way to fix the code (possibly a warning message is generated
for a perfectly fine piece of code). It would be unwise to offer
to suppress all warnings in such cases: the developer would miss
warnings about the rest of the code.</p>
<p>On the other hand, there are also situations conceivable where
some or all warnings are better treated as errors. For example,
it may be a local coding standard that a particular deprecated
feature should not be used. In order to enforce this, it is
useful to be able to turn the warning about this particular
feature into an error, raising an exception (without necessarily
turning all warnings into errors).</p>
<p>Therefore, I propose to introduce a flexible “warning filter”
which can filter out warnings or change them into exceptions,
based on:</p>
<ul class="simple">
<li>Where in the code they are generated (per package, module, or
function)</li>
<li>The warning category (warning categories are discussed below)</li>
<li>A specific warning message</li>
</ul>
<p>The warning filter must be controllable both from the command line
and from Python code.</p>
</section>
<section id="apis-for-issuing-warnings">
<h2><a class="toc-backref" href="#apis-for-issuing-warnings" role="doc-backlink">APIs For Issuing Warnings</a></h2>
<ul>
<li>To issue a warning from Python:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">warnings</span>
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="n">message</span><span class="p">[,</span> <span class="n">category</span><span class="p">[,</span> <span class="n">stacklevel</span><span class="p">]])</span>
</pre></div>
</div>
<p>The category argument, if given, must be a warning category
class (see below); it defaults to warnings.UserWarning. This
may raise an exception if the particular warning issued is
changed into an error by the warnings filter. The stacklevel
can be used by wrapper functions written in Python, like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">deprecation</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
<span class="n">warn</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="ne">DeprecationWarning</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
<p>This makes the warning refer to the deprecation()s caller,
rather than to the source of deprecation() itself (since the
latter would defeat the purpose of the warning message).</p>
</li>
<li>To issue a warning from C:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">PyErr_Warn</span><span class="p">(</span><span class="n">PyObject</span> <span class="o">*</span><span class="n">category</span><span class="p">,</span> <span class="n">char</span> <span class="o">*</span><span class="n">message</span><span class="p">);</span>
</pre></div>
</div>
<p>Return 0 normally, 1 if an exception is raised (either because
the warning was transformed into an exception, or because of a
malfunction in the implementation, such as running out of
memory). The category argument must be a warning category class
(see below) or <code class="docutils literal notranslate"><span class="pre">NULL</span></code>, in which case it defaults to
<code class="docutils literal notranslate"><span class="pre">PyExc_RuntimeWarning</span></code>. When <code class="docutils literal notranslate"><span class="pre">PyErr_Warn()</span></code> function returns 1, the
caller should do normal exception handling.</p>
<p>The current C implementation of <code class="docutils literal notranslate"><span class="pre">PyErr_Warn()</span></code> imports the
warnings module (implemented in Python) and calls its <code class="docutils literal notranslate"><span class="pre">warn()</span></code>
function. This minimizes the amount of C code that needs to be
added to implement the warning feature.</p>
<p>[XXX Open Issue: what about issuing warnings during lexing or
parsing, which dont have the exception machinery available?]</p>
</li>
</ul>
</section>
<section id="warnings-categories">
<h2><a class="toc-backref" href="#warnings-categories" role="doc-backlink">Warnings Categories</a></h2>
<p>There are a number of built-in exceptions that represent warning
categories. This categorization is useful to be able to filter
out groups of warnings. The following warnings category classes
are currently defined:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">Warning</span></code> this is the base class of all warning category
classes and it itself a subclass of Exception</li>
<li><code class="docutils literal notranslate"><span class="pre">UserWarning</span></code> the default category for <code class="docutils literal notranslate"><span class="pre">warnings.warn()</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code> base category for warnings about deprecated
features</li>
<li><code class="docutils literal notranslate"><span class="pre">SyntaxWarning</span></code> base category for warnings about dubious
syntactic features</li>
<li><code class="docutils literal notranslate"><span class="pre">RuntimeWarning</span></code> base category for warnings about dubious
runtime features</li>
</ul>
<p>[XXX: Other warning categories may be proposed during the review
period for this PEP.]</p>
<p>These standard warning categories are available from C as
<code class="docutils literal notranslate"><span class="pre">PyExc_Warning</span></code>, <code class="docutils literal notranslate"><span class="pre">PyExc_UserWarning</span></code>, etc. From Python, they are
available in the <code class="docutils literal notranslate"><span class="pre">__builtin__</span></code> module, so no import is necessary.</p>
<p>User code can define additional warning categories by subclassing
one of the standard warning categories. A warning category must
always be a subclass of the Warning class.</p>
</section>
<section id="the-warnings-filter">
<h2><a class="toc-backref" href="#the-warnings-filter" role="doc-backlink">The Warnings Filter</a></h2>
<p>The warnings filter control whether warnings are ignored,
displayed, or turned into errors (raising an exception).</p>
<p>There are three sides to the warnings filter:</p>
<ul class="simple">
<li>The data structures used to efficiently determine the
disposition of a particular <code class="docutils literal notranslate"><span class="pre">warnings.warn()</span></code> or <code class="docutils literal notranslate"><span class="pre">PyErr_Warn()</span></code>
call.</li>
<li>The API to control the filter from Python source code.</li>
<li>The command line switches to control the filter.</li>
</ul>
<p>The warnings filter works in several stages. It is optimized for
the (expected to be common) case where the same warning is issued
from the same place in the code over and over.</p>
<p>First, the warning filter collects the module and line number
where the warning is issued; this information is readily available
through <code class="docutils literal notranslate"><span class="pre">sys._getframe()</span></code>.</p>
<p>Conceptually, the warnings filter maintains an ordered list of
filter specifications; any specific warning is matched against
each filter specification in the list in turn until a match is
found; the match determines the disposition of the match. Each
entry is a tuple as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">category</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">module</span><span class="p">,</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">action</span><span class="p">)</span>
</pre></div>
</div>
<ul class="simple">
<li>category is a class (a subclass of <code class="docutils literal notranslate"><span class="pre">warnings.Warning</span></code>) of which
the warning category must be a subclass in order to match</li>
<li>message is a compiled regular expression that the warning
message must match (the match is case-insensitive)</li>
<li>module is a compiled regular expression that the module name
must match</li>
<li>lineno is an integer that the line number where the warning
occurred must match, or 0 to match all line numbers</li>
<li>action is one of the following strings:<ul>
<li>“error” turn matching warnings into exceptions</li>
<li>“ignore” never print matching warnings</li>
<li>“always” always print matching warnings</li>
<li>“default” print the first occurrence of matching warnings
for each location where the warning is issued</li>
<li>“module” print the first occurrence of matching warnings
for each module where the warning is issued</li>
<li>“once” print only the first occurrence of matching
warnings</li>
</ul>
</li>
</ul>
<p>Since the <code class="docutils literal notranslate"><span class="pre">Warning</span></code> class is derived from the built-in <code class="docutils literal notranslate"><span class="pre">Exception</span></code>
class, to turn a warning into an error we simply raise
<code class="docutils literal notranslate"><span class="pre">category(message)</span></code>.</p>
</section>
<section id="warnings-output-and-formatting-hooks">
<h2><a class="toc-backref" href="#warnings-output-and-formatting-hooks" role="doc-backlink">Warnings Output And Formatting Hooks</a></h2>
<p>When the warnings filter decides to issue a warning (but not when
it decides to raise an exception), it passes the information about
the function <code class="docutils literal notranslate"><span class="pre">warnings.showwarning(message,</span> <span class="pre">category,</span> <span class="pre">filename,</span> <span class="pre">lineno)</span></code>.
The default implementation of this function writes the warning text
to <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code>, and shows the source line of the filename. It has
an optional 5th argument which can be used to specify a different
file than <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code>.</p>
<p>The formatting of warnings is done by a separate function,
<code class="docutils literal notranslate"><span class="pre">warnings.formatwarning(message,</span> <span class="pre">category,</span> <span class="pre">filename,</span> <span class="pre">lineno)</span></code>. This
returns a string (that may contain newlines and ends in a newline)
that can be printed to get the identical effect of the
<code class="docutils literal notranslate"><span class="pre">showwarning()</span></code> function.</p>
</section>
<section id="api-for-manipulating-warning-filters">
<h2><a class="toc-backref" href="#api-for-manipulating-warning-filters" role="doc-backlink">API For Manipulating Warning Filters</a></h2>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">warnings</span><span class="o">.</span><span class="n">filterwarnings</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">category</span><span class="p">,</span> <span class="n">module</span><span class="p">,</span> <span class="n">lineno</span><span class="p">,</span> <span class="n">action</span><span class="p">)</span>
</pre></div>
</div>
<p>This checks the types of the arguments, compiles the message and
module regular expressions, and inserts them as a tuple in front
of the warnings filter.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">warnings</span><span class="o">.</span><span class="n">resetwarnings</span><span class="p">()</span>
</pre></div>
</div>
<p>Reset the warnings filter to empty.</p>
</section>
<section id="command-line-syntax">
<h2><a class="toc-backref" href="#command-line-syntax" role="doc-backlink">Command Line Syntax</a></h2>
<p>There should be command line options to specify the most common
filtering actions, which I expect to include at least:</p>
<ul class="simple">
<li>suppress all warnings</li>
<li>suppress a particular warning message everywhere</li>
<li>suppress all warnings in a particular module</li>
<li>turn all warnings into exceptions</li>
</ul>
<p>I propose the following command line option syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">-</span><span class="n">Waction</span><span class="p">[:</span><span class="n">message</span><span class="p">[:</span><span class="n">category</span><span class="p">[:</span><span class="n">module</span><span class="p">[:</span><span class="n">lineno</span><span class="p">]]]]</span>
</pre></div>
</div>
<p>Where:</p>
<ul class="simple">
<li>action is an abbreviation of one of the allowed actions
(“error”, “default”, “ignore”, “always”, “once”, or “module”)</li>
<li>message is a message string; matches warnings whose message
text is an initial substring of message (matching is
case-insensitive)</li>
<li>category is an abbreviation of a standard warning category
class name <strong>or</strong> a fully-qualified name for a user-defined
warning category class of the form [package.]module.classname</li>
<li>module is a module name (possibly package.module)</li>
<li>lineno is an integral line number</li>
</ul>
<p>All parts except action may be omitted, where an empty value
after stripping whitespace is the same as an omitted value.</p>
<p>The C code that parses the Python command line saves the body of
all -W options in a list of strings, which is made available to
the warnings module as sys.warnoptions. The warnings module
parses these when it is first imported. Errors detected during
the parsing of sys.warnoptions are not fatal; a message is written
to sys.stderr and processing continues with the option.</p>
<p>Examples:</p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">-Werror</span></code></dt><dd>Turn all warnings into errors</dd>
<dt><code class="docutils literal notranslate"><span class="pre">-Wall</span></code></dt><dd>Show all warnings</dd>
<dt><code class="docutils literal notranslate"><span class="pre">-Wignore</span></code></dt><dd>Ignore all warnings</dd>
<dt><code class="docutils literal notranslate"><span class="pre">-Wi:hello</span></code></dt><dd>Ignore warnings whose message text starts with “hello”</dd>
<dt><code class="docutils literal notranslate"><span class="pre">-We::Deprecation</span></code></dt><dd>Turn deprecation warnings into errors</dd>
<dt><code class="docutils literal notranslate"><span class="pre">-Wi:::spam:10</span></code></dt><dd>Ignore all warnings on line 10 of module spam</dd>
<dt><code class="docutils literal notranslate"><span class="pre">-Wi:::spam</span> <span class="pre">-Wd:::spam:10</span></code></dt><dd>Ignore all warnings in module spam except on line 10</dd>
<dt><code class="docutils literal notranslate"><span class="pre">-We::Deprecation</span> <span class="pre">-Wd::Deprecation:spam</span></code></dt><dd>Turn deprecation warnings into errors except in module spam</dd>
</dl>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
<p>Some open issues off the top of my head:</p>
<ul class="simple">
<li>What about issuing warnings during lexing or parsing, which
dont have the exception machinery available?</li>
<li>The proposed command line syntax is a bit ugly (although the
simple cases arent so bad: <code class="docutils literal notranslate"><span class="pre">-Werror</span></code>, <code class="docutils literal notranslate"><span class="pre">-Wignore</span></code>, etc.). Anybody
got a better idea?</li>
<li>Im a bit worried that the filter specifications are too
complex. Perhaps filtering only on category and module (not on
message text and line number) would be enough?</li>
<li>Theres a bit of confusion between module names and file names.
The reporting uses file names, but the filter specification uses
module names. Maybe it should allow filenames as well?</li>
<li>Im not at all convinced that packages are handled right.</li>
<li>Do we need more standard warning categories? Fewer?</li>
<li>In order to minimize the start-up overhead, the warnings module
is imported by the first call to <code class="docutils literal notranslate"><span class="pre">PyErr_Warn()</span></code>. It does the
command line parsing for <code class="docutils literal notranslate"><span class="pre">-W</span></code> options upon import. Therefore, it
is possible that warning-free programs will not complain about
invalid <code class="docutils literal notranslate"><span class="pre">-W</span></code> options.</li>
</ul>
</section>
<section id="rejected-concerns">
<h2><a class="toc-backref" href="#rejected-concerns" role="doc-backlink">Rejected Concerns</a></h2>
<p>Paul Prescod, Barry Warsaw and Fred Drake have brought up several
additional concerns that I feel arent critical. I address them
here (the concerns are paraphrased, not exactly their words):</p>
<ul>
<li>Paul: <code class="docutils literal notranslate"><span class="pre">warn()</span></code> should be a built-in or a statement to make it easily
available.<p>Response: “from warnings import warn” is easy enough.</p>
</li>
<li>Paul: What if I have a speed-critical module that triggers
warnings in an inner loop. It should be possible to disable the
overhead for detecting the warning (not just suppress the
warning).<p>Response: rewrite the inner loop to avoid triggering the
warning.</p>
</li>
<li>Paul: What if I want to see the full context of a warning?<p>Response: use <code class="docutils literal notranslate"><span class="pre">-Werror</span></code> to turn it into an exception.</p>
</li>
<li>Paul: I prefer “:*:*:” to “:::” for leaving parts of the warning
spec out.<p>Response: I dont.</p>
</li>
<li>Barry: It would be nice if lineno can be a range specification.<p>Response: Too much complexity already.</p>
</li>
<li>Barry: Id like to add my own warning action. Maybe if action
could be a callable as well as a string. Then in my IDE, I
could set that to “mygui.popupWarningsDialog”.<p>Response: For that purpose you would override
<code class="docutils literal notranslate"><span class="pre">warnings.showwarning()</span></code>.</p>
</li>
<li>Fred: why do the Warning category classes have to be in
<code class="docutils literal notranslate"><span class="pre">__builtin__</span></code>?<p>Response: thats the simplest implementation, given that the
warning categories must be available in C before the first
<code class="docutils literal notranslate"><span class="pre">PyErr_Warn()</span></code> call, which imports the warnings module. I see no
problem with making them available as built-ins.</p>
</li>
</ul>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>Heres a prototype implementation:
<a class="reference external" href="http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=102715&amp;group_id=5470">http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=102715&amp;group_id=5470</a></p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0230.rst">https://github.com/python/peps/blob/main/peps/pep-0230.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0230.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#apis-for-issuing-warnings">APIs For Issuing Warnings</a></li>
<li><a class="reference internal" href="#warnings-categories">Warnings Categories</a></li>
<li><a class="reference internal" href="#the-warnings-filter">The Warnings Filter</a></li>
<li><a class="reference internal" href="#warnings-output-and-formatting-hooks">Warnings Output And Formatting Hooks</a></li>
<li><a class="reference internal" href="#api-for-manipulating-warning-filters">API For Manipulating Warning Filters</a></li>
<li><a class="reference internal" href="#command-line-syntax">Command Line Syntax</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#rejected-concerns">Rejected Concerns</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0230.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

752
pep-0231/index.html Normal file
View File

@ -0,0 +1,752 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 231 __findattr__() | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0231/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 231 __findattr__() | peps.python.org'>
<meta property="og:description" content="This PEP describes an extension to instance attribute lookup and modification machinery, which allows pure-Python implementations of many interesting programming models. This PEP tracks the status and ownership of this feature. It contains a descripti...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0231/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes an extension to instance attribute lookup and modification machinery, which allows pure-Python implementations of many interesting programming models. This PEP tracks the status and ownership of this feature. It contains a descripti...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 231</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 231 __findattr__()</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">30-Nov-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#key-differences-with-the-existing-protocol">Key Differences with the Existing Protocol</a></li>
<li><a class="reference internal" href="#related-work">Related Work</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#rejection">Rejection</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes an extension to instance attribute lookup and
modification machinery, which allows pure-Python implementations
of many interesting programming models. This PEP tracks the
status and ownership of this feature. It contains a description
of the feature and outlines changes necessary to support the
feature. This PEP summarizes discussions held in mailing list
forums, and provides URLs for further information, where
appropriate. The CVS revision history of this file contains the
definitive historical record.</p>
</section>
<section id="background">
<h2><a class="toc-backref" href="#background" role="doc-backlink">Background</a></h2>
<p>The semantics for Python instances allow the programmer to
customize some aspects of attribute lookup and attribute
modification, through the special methods <code class="docutils literal notranslate"><span class="pre">__getattr__()</span></code> and
<code class="docutils literal notranslate"><span class="pre">__setattr__()</span></code> <a class="footnote-reference brackets" href="#id7" id="id1">[1]</a>.</p>
<p>However, because of certain restrictions imposed by these methods,
there are useful programming techniques that can not be written in
Python alone, e.g. strict Java Bean-like <a class="footnote-reference brackets" href="#id8" id="id2">[2]</a> interfaces and Zope
style acquisitions <a class="footnote-reference brackets" href="#id9" id="id3">[3]</a>. In the latter case, Zope solves this by
including a C extension called ExtensionClass <a class="footnote-reference brackets" href="#id10" id="id4">[5]</a> which modifies
the standard class semantics, and uses a metaclass hook in
Pythons class model called alternatively the “Don Beaudry Hook”
or “Don Beaudry Hack” <a class="footnote-reference brackets" href="#id11" id="id5">[6]</a>.</p>
<p>While Zopes approach works, it has several disadvantages. First,
it requires a C extension. Second it employs a very arcane, but
truck-sized loophole in the Python machinery. Third, it can be
difficult for other programmers to use and understand (the
metaclass has well-known brain exploding properties). And fourth,
because ExtensionClass instances arent “real” Python instances,
some aspects of the Python runtime system dont work with
ExtensionClass instances.</p>
<p>Proposals for fixing this problem have often been lumped under the
rubric of fixing the “class/type dichotomy”; that is, eliminating
the difference between built-in types and classes <a class="footnote-reference brackets" href="#id12" id="id6">[7]</a>. While a
laudable goal itself, repairing this rift is not necessary in
order to achieve the types of programming constructs described
above. This proposal provides an 80% solution with a minimum of
modification to Pythons class and instance objects. It does
nothing to address the type/class dichotomy.</p>
</section>
<section id="proposal">
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
<p>This proposal adds a new special method called <code class="docutils literal notranslate"><span class="pre">__findattr__()</span></code> with
the following semantics:</p>
<ul class="simple">
<li>If defined in a class, it will be called on all instance
attribute resolutions instead of <code class="docutils literal notranslate"><span class="pre">__getattr__()</span></code> and
<code class="docutils literal notranslate"><span class="pre">__setattr__()</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">__findattr__()</span></code> is never called recursively. That is, when a
specific instances <code class="docutils literal notranslate"><span class="pre">__findattr__()</span></code> is on the call stack, further
attribute accesses for that instance will use the standard
<code class="docutils literal notranslate"><span class="pre">__getattr__()</span></code> and <code class="docutils literal notranslate"><span class="pre">__setattr__()</span></code> methods.</li>
<li><code class="docutils literal notranslate"><span class="pre">__findattr__()</span></code> is called for both attribute access (getting)
and attribute modification (setting). It is not called for
attribute deletion.</li>
<li>When called for getting, it is passed a single argument (not
counting self): the name of the attribute being accessed.</li>
<li>When called for setting, it is called with third argument, which
is the value to set the attribute to.</li>
<li><code class="docutils literal notranslate"><span class="pre">__findattr__()</span></code> methods have the same caching semantics as
<code class="docutils literal notranslate"><span class="pre">__getattr__()</span></code> and <code class="docutils literal notranslate"><span class="pre">__setattr__()</span></code>; i.e. if they are present in the
class at class definition time, they are used, but if they are
subsequently added to a class later they are not.</li>
</ul>
</section>
<section id="key-differences-with-the-existing-protocol">
<h2><a class="toc-backref" href="#key-differences-with-the-existing-protocol" role="doc-backlink">Key Differences with the Existing Protocol</a></h2>
<p><code class="docutils literal notranslate"><span class="pre">__findattr__()</span></code>s semantics are different from the existing
protocol in key ways:</p>
<p>First, <code class="docutils literal notranslate"><span class="pre">__getattr__()</span></code> is never called if the attribute is found in
the instances <code class="docutils literal notranslate"><span class="pre">__dict__</span></code>. This is done for efficiency reasons, and
because otherwise, <code class="docutils literal notranslate"><span class="pre">__setattr__()</span></code> would have no way to get to the
instances attributes.</p>
<p>Second, <code class="docutils literal notranslate"><span class="pre">__setattr__()</span></code> cannot use “normal” syntax for setting
instance attributes, e.g. “self.name = foo” because that would
cause recursive calls to <code class="docutils literal notranslate"><span class="pre">__setattr__()</span></code>.</p>
<p><code class="docutils literal notranslate"><span class="pre">__findattr__()</span></code> is always called regardless of whether the
attribute is in <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> or not, and a flag in the instance object
prevents recursive calls to <code class="docutils literal notranslate"><span class="pre">__findattr__()</span></code>. This gives the class
a chance to perform some action for every attribute access. And
because it is called for both gets and sets, it is easy to write
similar policy for all attribute access. Further, efficiency is
not a problem because it is only paid when the extended mechanism
is used.</p>
</section>
<section id="related-work">
<h2><a class="toc-backref" href="#related-work" role="doc-backlink">Related Work</a></h2>
<p><a class="pep reference internal" href="../pep-0213/" title="PEP 213 Attribute Access Handlers">PEP 213</a> describes a different approach to hooking into
attribute access and modification. The semantics proposed in <a class="pep reference internal" href="../pep-0213/" title="PEP 213 Attribute Access Handlers">PEP 213</a>
can be implemented using the <code class="docutils literal notranslate"><span class="pre">__findattr__()</span></code> hook described
here, with one caveat. The current reference implementation of
<code class="docutils literal notranslate"><span class="pre">__findattr__()</span></code> does not support hooking on attribute deletion.
This could be added if its found desirable. See example below.</p>
</section>
<section id="examples">
<h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2>
<p>One programming style that this proposal allows is a Java
Bean-like interface to objects, where unadorned attribute access
and modification is transparently mapped to a functional
interface. E.g.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Bean</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__myfoo</span> <span class="o">=</span> <span class="n">x</span>
<span class="k">def</span> <span class="nf">__findattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="k">if</span> <span class="n">name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;_&#39;</span><span class="p">):</span>
<span class="c1"># Private names</span>
<span class="k">if</span> <span class="n">args</span><span class="p">:</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Public names</span>
<span class="k">if</span> <span class="n">args</span><span class="p">:</span> <span class="n">name</span> <span class="o">=</span> <span class="s1">&#39;_set_&#39;</span> <span class="o">+</span> <span class="n">name</span>
<span class="k">else</span><span class="p">:</span> <span class="n">name</span> <span class="o">=</span> <span class="s1">&#39;_get_&#39;</span> <span class="o">+</span> <span class="n">name</span>
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">)(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_set_foo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__myfoo</span> <span class="o">=</span> <span class="n">x</span>
<span class="k">def</span> <span class="nf">_get_foo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__myfoo</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">Bean</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="nb">print</span> <span class="n">b</span><span class="o">.</span><span class="n">foo</span>
<span class="n">b</span><span class="o">.</span><span class="n">foo</span> <span class="o">=</span> <span class="mi">9</span>
<span class="nb">print</span> <span class="n">b</span><span class="o">.</span><span class="n">foo</span>
</pre></div>
</div>
<p>A second, more elaborate example is the implementation of both
implicit and explicit acquisition in pure Python:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">types</span>
<span class="k">class</span> <span class="nc">MethodWrapper</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span> <span class="n">method</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__container</span> <span class="o">=</span> <span class="n">container</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__method</span> <span class="o">=</span> <span class="n">method</span>
<span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kws</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__method</span><span class="o">.</span><span class="n">im_func</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__container</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kws</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">WrapperImplicit</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">contained</span><span class="p">,</span> <span class="n">container</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__contained</span> <span class="o">=</span> <span class="n">contained</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__container</span> <span class="o">=</span> <span class="n">container</span>
<span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s1">&#39;&lt;Wrapper: [</span><span class="si">%s</span><span class="s1"> | </span><span class="si">%s</span><span class="s1">]&gt;&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__container</span><span class="p">,</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__contained</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__findattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="c1"># Some things are our own</span>
<span class="k">if</span> <span class="n">name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;_WrapperImplicit__&#39;</span><span class="p">):</span>
<span class="k">if</span> <span class="n">args</span><span class="p">:</span> <span class="k">return</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="c1"># setattr stores the name on the contained object directly</span>
<span class="k">if</span> <span class="n">args</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__contained</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="c1"># Other special names</span>
<span class="k">if</span> <span class="n">name</span> <span class="o">==</span> <span class="s1">&#39;aq_parent&#39;</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__container</span>
<span class="k">elif</span> <span class="n">name</span> <span class="o">==</span> <span class="s1">&#39;aq_self&#39;</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__contained</span>
<span class="k">elif</span> <span class="n">name</span> <span class="o">==</span> <span class="s1">&#39;aq_base&#39;</span><span class="p">:</span>
<span class="n">base</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__contained</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">base</span> <span class="o">=</span> <span class="n">base</span><span class="o">.</span><span class="n">aq_self</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="k">return</span> <span class="n">base</span>
<span class="c1"># no acquisition for _ names</span>
<span class="k">if</span> <span class="n">name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;_&#39;</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__contained</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="c1"># Everything else gets wrapped</span>
<span class="n">missing</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">which</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__contained</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">which</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">missing</span><span class="p">)</span>
<span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="n">missing</span><span class="p">:</span>
<span class="n">which</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__container</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">which</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">missing</span><span class="p">)</span>
<span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="n">missing</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">,</span> <span class="n">name</span>
<span class="n">of</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s1">&#39;__of__&#39;</span><span class="p">,</span> <span class="n">missing</span><span class="p">)</span>
<span class="k">if</span> <span class="n">of</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">missing</span><span class="p">:</span>
<span class="k">return</span> <span class="n">of</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">type</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="o">==</span> <span class="n">types</span><span class="o">.</span><span class="n">MethodType</span><span class="p">:</span>
<span class="k">return</span> <span class="n">MethodWrapper</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">)</span>
<span class="k">return</span> <span class="n">obj</span>
<span class="k">class</span> <span class="nc">WrapperExplicit</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">contained</span><span class="p">,</span> <span class="n">container</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__contained</span> <span class="o">=</span> <span class="n">contained</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__container</span> <span class="o">=</span> <span class="n">container</span>
<span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s1">&#39;&lt;Wrapper: [</span><span class="si">%s</span><span class="s1"> | </span><span class="si">%s</span><span class="s1">]&gt;&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__container</span><span class="p">,</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__contained</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__findattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="c1"># Some things are our own</span>
<span class="k">if</span> <span class="n">name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;_WrapperExplicit__&#39;</span><span class="p">):</span>
<span class="k">if</span> <span class="n">args</span><span class="p">:</span> <span class="k">return</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="c1"># setattr stores the name on the contained object directly</span>
<span class="k">if</span> <span class="n">args</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__contained</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="c1"># Other special names</span>
<span class="k">if</span> <span class="n">name</span> <span class="o">==</span> <span class="s1">&#39;aq_parent&#39;</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__container</span>
<span class="k">elif</span> <span class="n">name</span> <span class="o">==</span> <span class="s1">&#39;aq_self&#39;</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__contained</span>
<span class="k">elif</span> <span class="n">name</span> <span class="o">==</span> <span class="s1">&#39;aq_base&#39;</span><span class="p">:</span>
<span class="n">base</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__contained</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">base</span> <span class="o">=</span> <span class="n">base</span><span class="o">.</span><span class="n">aq_self</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="k">return</span> <span class="n">base</span>
<span class="k">elif</span> <span class="n">name</span> <span class="o">==</span> <span class="s1">&#39;aq_acquire&#39;</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">aq_acquire</span>
<span class="c1"># explicit acquisition only</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__contained</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="o">==</span> <span class="n">types</span><span class="o">.</span><span class="n">MethodType</span><span class="p">:</span>
<span class="k">return</span> <span class="n">MethodWrapper</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">)</span>
<span class="k">return</span> <span class="n">obj</span>
<span class="k">def</span> <span class="nf">aq_acquire</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="c1"># Everything else gets wrapped</span>
<span class="n">missing</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">which</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__contained</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">which</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">missing</span><span class="p">)</span>
<span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="n">missing</span><span class="p">:</span>
<span class="n">which</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__container</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">which</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">missing</span><span class="p">)</span>
<span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="n">missing</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">,</span> <span class="n">name</span>
<span class="n">of</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s1">&#39;__of__&#39;</span><span class="p">,</span> <span class="n">missing</span><span class="p">)</span>
<span class="k">if</span> <span class="n">of</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">missing</span><span class="p">:</span>
<span class="k">return</span> <span class="n">of</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">type</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="o">==</span> <span class="n">types</span><span class="o">.</span><span class="n">MethodType</span><span class="p">:</span>
<span class="k">return</span> <span class="n">MethodWrapper</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">)</span>
<span class="k">return</span> <span class="n">obj</span>
<span class="k">class</span> <span class="nc">Implicit</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__of__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">container</span><span class="p">):</span>
<span class="k">return</span> <span class="n">WrapperImplicit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">container</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__findattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="c1"># ignore setattrs</span>
<span class="k">if</span> <span class="n">args</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="n">missing</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">of</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="s1">&#39;__of__&#39;</span><span class="p">,</span> <span class="n">missing</span><span class="p">)</span>
<span class="k">if</span> <span class="n">of</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">missing</span><span class="p">:</span>
<span class="k">return</span> <span class="n">of</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">return</span> <span class="n">obj</span>
<span class="k">class</span> <span class="nc">Explicit</span><span class="p">(</span><span class="n">Implicit</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__of__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">container</span><span class="p">):</span>
<span class="k">return</span> <span class="n">WrapperExplicit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">container</span><span class="p">)</span>
<span class="c1"># tests</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="n">Implicit</span><span class="p">):</span>
<span class="n">color</span> <span class="o">=</span> <span class="s1">&#39;red&#39;</span>
<span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">Implicit</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">report</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">color</span>
<span class="c1"># simple implicit acquisition</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">A</span><span class="p">()</span>
<span class="n">c</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="n">a</span>
<span class="k">assert</span> <span class="n">c</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">report</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;red&#39;</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">d</span><span class="o">.</span><span class="n">color</span> <span class="o">=</span> <span class="s1">&#39;green&#39;</span>
<span class="n">d</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="n">a</span>
<span class="k">assert</span> <span class="n">d</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">report</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;green&#39;</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">a</span><span class="o">.</span><span class="n">report</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">assert</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;AttributeError expected&#39;</span>
<span class="c1"># special names</span>
<span class="k">assert</span> <span class="n">c</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">aq_parent</span> <span class="ow">is</span> <span class="n">c</span>
<span class="k">assert</span> <span class="n">c</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">aq_self</span> <span class="ow">is</span> <span class="n">a</span>
<span class="n">c</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">d</span> <span class="o">=</span> <span class="n">d</span>
<span class="k">assert</span> <span class="n">c</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">d</span><span class="o">.</span><span class="n">aq_base</span> <span class="ow">is</span> <span class="n">d</span>
<span class="k">assert</span> <span class="n">c</span><span class="o">.</span><span class="n">a</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">a</span>
<span class="c1"># no acquisition on _ names</span>
<span class="k">class</span> <span class="nc">E</span><span class="p">(</span><span class="n">Implicit</span><span class="p">):</span>
<span class="n">_color</span> <span class="o">=</span> <span class="s1">&#39;purple&#39;</span>
<span class="k">class</span> <span class="nc">F</span><span class="p">(</span><span class="n">Implicit</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">report</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_color</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">E</span><span class="p">()</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">F</span><span class="p">()</span>
<span class="n">e</span><span class="o">.</span><span class="n">f</span> <span class="o">=</span> <span class="n">f</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">e</span><span class="o">.</span><span class="n">f</span><span class="o">.</span><span class="n">report</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">assert</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;AttributeError expected&#39;</span>
<span class="c1"># explicit</span>
<span class="k">class</span> <span class="nc">G</span><span class="p">(</span><span class="n">Explicit</span><span class="p">):</span>
<span class="n">color</span> <span class="o">=</span> <span class="s1">&#39;pink&#39;</span>
<span class="k">class</span> <span class="nc">H</span><span class="p">(</span><span class="n">Explicit</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">report</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">aq_acquire</span><span class="p">(</span><span class="s1">&#39;color&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">barf</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">color</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">G</span><span class="p">()</span>
<span class="n">h</span> <span class="o">=</span> <span class="n">H</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">h</span> <span class="o">=</span> <span class="n">h</span>
<span class="k">assert</span> <span class="n">g</span><span class="o">.</span><span class="n">h</span><span class="o">.</span><span class="n">report</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;pink&#39;</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">G</span><span class="p">()</span>
<span class="n">i</span><span class="o">.</span><span class="n">color</span> <span class="o">=</span> <span class="s1">&#39;cyan&#39;</span>
<span class="n">i</span><span class="o">.</span><span class="n">h</span> <span class="o">=</span> <span class="n">h</span>
<span class="k">assert</span> <span class="n">i</span><span class="o">.</span><span class="n">h</span><span class="o">.</span><span class="n">report</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;cyan&#39;</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">g</span><span class="o">.</span><span class="n">i</span><span class="o">.</span><span class="n">barf</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">assert</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;AttributeError expected&#39;</span>
</pre></div>
</div>
<p>C++-like access control can also be accomplished, although less
cleanly because of the difficulty of figuring out what method is
being called from the runtime call stack:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">types</span>
<span class="n">PUBLIC</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">PROTECTED</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">PRIVATE</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">getframe</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">_getframe</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">getframe</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">Exception</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">frame</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">tb_frame</span>
<span class="k">while</span> <span class="n">n</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">frame</span> <span class="o">=</span> <span class="n">frame</span><span class="o">.</span><span class="n">f_back</span>
<span class="k">if</span> <span class="n">frame</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">,</span> <span class="s1">&#39;call stack is not deep enough&#39;</span>
<span class="k">return</span> <span class="n">frame</span>
<span class="k">class</span> <span class="nc">AccessViolation</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">Access</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__findattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">methcache</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s1">&#39;__cache__&#39;</span><span class="p">,</span> <span class="p">{})</span>
<span class="n">missing</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">missing</span><span class="p">)</span>
<span class="c1"># if obj is missing we better be doing a setattr for</span>
<span class="c1"># the first time</span>
<span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">missing</span> <span class="ow">and</span> <span class="nb">type</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="o">==</span> <span class="n">types</span><span class="o">.</span><span class="n">MethodType</span><span class="p">:</span>
<span class="c1"># Digusting hack because there&#39;s no way to</span>
<span class="c1"># dynamically figure out what the method being</span>
<span class="c1"># called is from the stack frame.</span>
<span class="n">methcache</span><span class="p">[</span><span class="n">obj</span><span class="o">.</span><span class="n">im_func</span><span class="o">.</span><span class="n">func_code</span><span class="p">]</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">im_class</span>
<span class="c1">#</span>
<span class="c1"># What&#39;s the access permissions for this name?</span>
<span class="n">access</span><span class="p">,</span> <span class="n">klass</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">&#39;__access__&#39;</span><span class="p">,</span> <span class="p">{})</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
<span class="n">name</span><span class="p">,</span> <span class="p">(</span><span class="n">PUBLIC</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
<span class="k">if</span> <span class="n">access</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">PUBLIC</span><span class="p">:</span>
<span class="c1"># Now try to see which method is calling us</span>
<span class="n">frame</span> <span class="o">=</span> <span class="n">getframe</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">f_back</span>
<span class="k">if</span> <span class="n">frame</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">AccessViolation</span>
<span class="c1"># Get the class of the method that&#39;s accessing</span>
<span class="c1"># this attribute, by using the code object cache</span>
<span class="k">if</span> <span class="n">frame</span><span class="o">.</span><span class="n">f_code</span><span class="o">.</span><span class="n">co_name</span> <span class="o">==</span> <span class="s1">&#39;__init__&#39;</span><span class="p">:</span>
<span class="c1"># There aren&#39;t entries in the cache for ctors,</span>
<span class="c1"># because the calling mechanism doesn&#39;t go</span>
<span class="c1"># through __findattr__(). Are there other</span>
<span class="c1"># methods that might have the same behavior?</span>
<span class="c1"># Since we can&#39;t know who&#39;s __init__ we&#39;re in,</span>
<span class="c1"># for now we&#39;ll assume that only protected and</span>
<span class="c1"># public attrs can be accessed.</span>
<span class="k">if</span> <span class="n">access</span> <span class="ow">is</span> <span class="n">PRIVATE</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">AccessViolation</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">methclass</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__cache__</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">frame</span><span class="o">.</span><span class="n">f_code</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">methclass</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">AccessViolation</span>
<span class="k">if</span> <span class="n">access</span> <span class="ow">is</span> <span class="n">PRIVATE</span> <span class="ow">and</span> <span class="n">methclass</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">klass</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">AccessViolation</span>
<span class="k">if</span> <span class="n">access</span> <span class="ow">is</span> <span class="n">PROTECTED</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">issubclass</span><span class="p">(</span><span class="n">methclass</span><span class="p">,</span>
<span class="n">klass</span><span class="p">):</span>
<span class="k">raise</span> <span class="n">AccessViolation</span>
<span class="c1"># If we got here, it must be okay to access the attribute</span>
<span class="k">if</span> <span class="n">args</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="k">return</span> <span class="n">obj</span>
<span class="c1"># tests</span>
<span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">Access</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">foo</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;A&#39;</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_foo</span> <span class="o">=</span> <span class="n">foo</span>
<span class="c1"># can&#39;t set private names in __init__</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__initprivate</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__initprivate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_name</span> <span class="o">=</span> <span class="n">name</span>
<span class="k">def</span> <span class="nf">getfoo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_foo</span>
<span class="k">def</span> <span class="nf">setfoo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">newfoo</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_foo</span> <span class="o">=</span> <span class="n">newfoo</span>
<span class="k">def</span> <span class="nf">getname</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_name</span>
<span class="n">A</span><span class="o">.</span><span class="n">__access__</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;_foo&#39;</span> <span class="p">:</span> <span class="p">(</span><span class="n">PROTECTED</span><span class="p">,</span> <span class="n">A</span><span class="p">),</span>
<span class="s1">&#39;_name&#39;</span> <span class="p">:</span> <span class="p">(</span><span class="n">PRIVATE</span><span class="p">,</span> <span class="n">A</span><span class="p">),</span>
<span class="s1">&#39;__dict__&#39;</span> <span class="p">:</span> <span class="p">(</span><span class="n">PRIVATE</span><span class="p">,</span> <span class="n">A</span><span class="p">),</span>
<span class="s1">&#39;__access__&#39;</span><span class="p">:</span> <span class="p">(</span><span class="n">PRIVATE</span><span class="p">,</span> <span class="n">A</span><span class="p">),</span>
<span class="p">}</span>
<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">A</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">setfoo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">newfoo</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_foo</span> <span class="o">=</span> <span class="n">newfoo</span> <span class="o">+</span> <span class="mi">3</span>
<span class="k">def</span> <span class="nf">setname</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_name</span> <span class="o">=</span> <span class="n">name</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">B</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">b</span><span class="o">.</span><span class="n">getfoo</span><span class="p">()</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">A</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">a</span><span class="o">.</span><span class="n">getfoo</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span>
<span class="n">a</span><span class="o">.</span><span class="n">setfoo</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">a</span><span class="o">.</span><span class="n">getfoo</span><span class="p">()</span> <span class="o">==</span> <span class="mi">2</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">a</span><span class="o">.</span><span class="n">_foo</span>
<span class="k">except</span> <span class="n">AccessViolation</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">assert</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;AccessViolation expected&#39;</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">a</span><span class="o">.</span><span class="n">_foo</span> <span class="o">=</span> <span class="mi">3</span>
<span class="k">except</span> <span class="n">AccessViolation</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">assert</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;AccessViolation expected&#39;</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">a</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">[</span><span class="s1">&#39;_foo&#39;</span><span class="p">]</span>
<span class="k">except</span> <span class="n">AccessViolation</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">assert</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;AccessViolation expected&#39;</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">B</span><span class="p">()</span>
<span class="k">assert</span> <span class="n">b</span><span class="o">.</span><span class="n">getfoo</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span>
<span class="n">b</span><span class="o">.</span><span class="n">setfoo</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">b</span><span class="o">.</span><span class="n">getfoo</span><span class="p">()</span> <span class="o">==</span> <span class="mi">5</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">b</span><span class="o">.</span><span class="n">setname</span><span class="p">(</span><span class="s1">&#39;B&#39;</span><span class="p">)</span>
<span class="k">except</span> <span class="n">AccessViolation</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">assert</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;AccessViolation expected&#39;</span>
<span class="k">assert</span> <span class="n">b</span><span class="o">.</span><span class="n">getname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;A&#39;</span>
</pre></div>
</div>
<p>Heres an implementation of the attribute hook described in PEP
213 (except that hooking on attribute deletion isnt supported by
the current reference implementation).</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Pep213</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__findattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="n">hookname</span> <span class="o">=</span> <span class="s1">&#39;__attr_</span><span class="si">%s</span><span class="s1">__&#39;</span> <span class="o">%</span> <span class="n">name</span>
<span class="k">if</span> <span class="n">args</span><span class="p">:</span>
<span class="n">op</span> <span class="o">=</span> <span class="s1">&#39;set&#39;</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">op</span> <span class="o">=</span> <span class="s1">&#39;get&#39;</span>
<span class="c1"># XXX: op = &#39;del&#39; currently not supported</span>
<span class="n">missing</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">meth</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">hookname</span><span class="p">,</span> <span class="n">missing</span><span class="p">)</span>
<span class="k">if</span> <span class="n">meth</span> <span class="ow">is</span> <span class="n">missing</span><span class="p">:</span>
<span class="k">if</span> <span class="n">op</span> <span class="o">==</span> <span class="s1">&#39;set&#39;</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">meth</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">computation</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
<span class="nb">print</span> <span class="s1">&#39;doing computation:&#39;</span><span class="p">,</span> <span class="n">i</span>
<span class="k">return</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">3</span>
<span class="k">def</span> <span class="nf">rev_computation</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
<span class="nb">print</span> <span class="s1">&#39;doing rev_computation:&#39;</span><span class="p">,</span> <span class="n">i</span>
<span class="k">return</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">3</span>
<span class="k">class</span> <span class="nc">X</span><span class="p">(</span><span class="n">Pep213</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">foo</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__foo</span> <span class="o">=</span> <span class="n">foo</span>
<span class="k">def</span> <span class="nf">__attr_foo__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">op</span><span class="p">,</span> <span class="n">val</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">if</span> <span class="n">op</span> <span class="o">==</span> <span class="s1">&#39;get&#39;</span><span class="p">:</span>
<span class="k">return</span> <span class="n">computation</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__foo</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">op</span> <span class="o">==</span> <span class="s1">&#39;set&#39;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">__foo</span> <span class="o">=</span> <span class="n">rev_computation</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>
<span class="c1"># XXX: &#39;del&#39; not yet supported</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">X</span><span class="p">()</span>
<span class="n">fooval</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="n">foo</span>
<span class="nb">print</span> <span class="n">fooval</span>
<span class="n">x</span><span class="o">.</span><span class="n">foo</span> <span class="o">=</span> <span class="n">fooval</span> <span class="o">+</span> <span class="mi">5</span>
<span class="nb">print</span> <span class="n">x</span><span class="o">.</span><span class="n">foo</span>
<span class="c1"># del x.foo</span>
</pre></div>
</div>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>The reference implementation, as a patch to the Python core, can be
found at this URL:</p>
<p><a class="reference external" href="http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=102613&amp;group_id=5470">http://sourceforge.net/patch/?func=detailpatch&amp;patch_id=102613&amp;group_id=5470</a></p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id7" role="doc-footnote">
<dt class="label" id="id7">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://docs.python.org/reference/datamodel.html#customizing-attribute-access">http://docs.python.org/reference/datamodel.html#customizing-attribute-access</a></aside>
<aside class="footnote brackets" id="id8" role="doc-footnote">
<dt class="label" id="id8">[<a href="#id2">2</a>]</dt>
<dd><a class="reference external" href="http://www.javasoft.com/products/javabeans/">http://www.javasoft.com/products/javabeans/</a></aside>
<aside class="footnote brackets" id="id9" role="doc-footnote">
<dt class="label" id="id9">[<a href="#id3">3</a>]</dt>
<dd><a class="reference external" href="http://www.digicool.com/releases/ExtensionClass/Acquisition.html">http://www.digicool.com/releases/ExtensionClass/Acquisition.html</a></aside>
<aside class="footnote brackets" id="id10" role="doc-footnote">
<dt class="label" id="id10">[<a href="#id4">5</a>]</dt>
<dd><a class="reference external" href="http://www.digicool.com/releases/ExtensionClass">http://www.digicool.com/releases/ExtensionClass</a></aside>
<aside class="footnote brackets" id="id11" role="doc-footnote">
<dt class="label" id="id11">[<a href="#id5">6</a>]</dt>
<dd><a class="reference external" href="http://www.python.org/doc/essays/metaclasses/">http://www.python.org/doc/essays/metaclasses/</a></aside>
<aside class="footnote brackets" id="id12" role="doc-footnote">
<dt class="label" id="id12">[<a href="#id6">7</a>]</dt>
<dd><a class="reference external" href="http://www.foretec.com/python/workshops/1998-11/dd-ascher-sum.html">http://www.foretec.com/python/workshops/1998-11/dd-ascher-sum.html</a></aside>
</aside>
<ul class="simple">
<li><a class="reference external" href="http://docs.python.org/howto/regex.html">http://docs.python.org/howto/regex.html</a></li>
</ul>
</section>
<section id="rejection">
<h2><a class="toc-backref" href="#rejection" role="doc-backlink">Rejection</a></h2>
<p>There are serious problems with the recursion-protection feature.
As described here its not thread-safe, and a thread-safe solution
has other problems. In general, its not clear how helpful the
recursion-protection feature is; it makes it hard to write code
that needs to be callable inside <code class="docutils literal notranslate"><span class="pre">__findattr__</span></code> as well as outside
it. But without the recursion-protection, its hard to implement
<code class="docutils literal notranslate"><span class="pre">__findattr__</span></code> at all (since <code class="docutils literal notranslate"><span class="pre">__findattr__</span></code> would invoke itself
recursively for every attribute it tries to access). There seems
to be no good solution here.</p>
<p>Its also dubious how useful it is to support <code class="docutils literal notranslate"><span class="pre">__findattr__</span></code> both
for getting and for setting attributes <code class="docutils literal notranslate"><span class="pre">__setattr__</span></code> gets called
in all cases already.</p>
<p>The examples can all be implemented using <code class="docutils literal notranslate"><span class="pre">__getattr__</span></code> if care is
taken not to store instance variables under their own names.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the Public Domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0231.rst">https://github.com/python/peps/blob/main/peps/pep-0231.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0231.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#key-differences-with-the-existing-protocol">Key Differences with the Existing Protocol</a></li>
<li><a class="reference internal" href="#related-work">Related Work</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#rejection">Rejection</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0231.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

364
pep-0232/index.html Normal file
View File

@ -0,0 +1,364 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 232 Function Attributes | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0232/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 232 Function Attributes | peps.python.org'>
<meta property="og:description" content="This PEP describes an extension to Python, adding attribute dictionaries to functions and methods. This PEP tracks the status and ownership of this feature. It contains a description of the feature and outlines changes necessary to support the feature...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0232/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes an extension to Python, adding attribute dictionaries to functions and methods. This PEP tracks the status and ownership of this feature. It contains a description of the feature and outlines changes necessary to support the feature...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 232</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 232 Function Attributes</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">02-Dec-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">20-Feb-2001</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#examples">Examples</a><ul>
<li><a class="reference internal" href="#other-uses">Other Uses</a></li>
</ul>
</li>
<li><a class="reference internal" href="#future-directions">Future Directions</a></li>
<li><a class="reference internal" href="#dissenting-opinion">Dissenting Opinion</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="introduction">
<h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2>
<p>This PEP describes an extension to Python, adding attribute
dictionaries to functions and methods. This PEP tracks the status
and ownership of this feature. It contains a description of the
feature and outlines changes necessary to support the feature.
This PEP summarizes discussions held in mailing list forums, and
provides URLs for further information, where appropriate. The CVS
revision history of this file contains the definitive historical
record.</p>
</section>
<section id="background">
<h2><a class="toc-backref" href="#background" role="doc-backlink">Background</a></h2>
<p>Functions already have a number of attributes, some of which are
writable, e.g. <code class="docutils literal notranslate"><span class="pre">func_doc</span></code>, a.k.a. <code class="docutils literal notranslate"><span class="pre">func.__doc__</span></code>. <code class="docutils literal notranslate"><span class="pre">func_doc</span></code>
has the interesting property that there is special syntax in
function (and method) definitions for implicitly setting the
attribute. This convenience has been exploited over and over again,
overloading docstrings with additional semantics.</p>
<p>For example, John Aycock has written a system where docstrings are
used to define parsing rules. <a class="footnote-reference brackets" href="#id4" id="id1">[1]</a> Zopes ZPublisher ORB <a class="footnote-reference brackets" href="#id5" id="id2">[2]</a> uses
docstrings to signal publishable methods, i.e. methods that can
be called through the web.</p>
<p>The problem with this approach is that the overloaded semantics
may conflict with each other. For example, if we wanted to add a
doctest unit test to a Zope method that should not be publishable
through the web.</p>
</section>
<section id="proposal">
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
<p>This proposal adds a new dictionary to function objects, called
<code class="docutils literal notranslate"><span class="pre">func_dict</span></code> (a.k.a. <code class="docutils literal notranslate"><span class="pre">__dict__</span></code>). This dictionary can be set
and get using ordinary attribute set and get syntax.</p>
<p>Methods also gain getter syntax, and they currently access the
attribute through the dictionary of the underlying function
object. It is not possible to set attributes on bound or unbound
methods, except by doing so explicitly on the underlying function
object. See the <a class="reference internal" href="#future-directions">Future Directions</a> discussion below for
approaches in subsequent versions of Python.</p>
<p>A function objects <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> can also be set, but only to a
dictionary object. Deleting a functions <code class="docutils literal notranslate"><span class="pre">__dict__</span></code>, or setting
it to anything other than a concrete dictionary object results in a
<code class="docutils literal notranslate"><span class="pre">TypeError</span></code>. If no function attributes have ever been set, the
functions <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> will be empty.</p>
</section>
<section id="examples">
<h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2>
<p>Here are some examples of what you can do with this feature.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">a</span><span class="p">():</span>
<span class="k">pass</span>
<span class="n">a</span><span class="o">.</span><span class="n">publish</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">a</span><span class="o">.</span><span class="n">unittest</span> <span class="o">=</span> <span class="s1">&#39;&#39;&#39;...&#39;&#39;&#39;</span>
<span class="k">if</span> <span class="n">a</span><span class="o">.</span><span class="n">publish</span><span class="p">:</span>
<span class="nb">print</span> <span class="n">a</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="s1">&#39;unittest&#39;</span><span class="p">):</span>
<span class="n">testframework</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">unittest</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">a</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s1">&#39;just a docstring&#39;</span>
<span class="n">a</span><span class="o">.</span><span class="n">publish</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="k">if</span> <span class="n">c</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">publish</span><span class="p">:</span>
<span class="n">publish</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">a</span><span class="p">())</span>
</pre></div>
</div>
<section id="other-uses">
<h3><a class="toc-backref" href="#other-uses" role="doc-backlink">Other Uses</a></h3>
<p>Paul Prescod enumerated a bunch of other uses on the <a class="reference external" href="https://mail.python.org/pipermail/python-dev/2000-April/003364.html">python-dev thread</a>.</p>
</section>
</section>
<section id="future-directions">
<h2><a class="toc-backref" href="#future-directions" role="doc-backlink">Future Directions</a></h2>
<p>Here are a number of future directions to consider. Any adoption
of these ideas would require a new PEP, which referenced this one,
and would have to be targeted at a Python version subsequent to
the 2.1 release.</p>
<ul>
<li>A previous version of this PEP allowed for both setter and
getter of attributes on unbound methods, and only getter on
bound methods. A number of problems were discovered with this
policy.<p>Because method attributes were stored in the underlying
function, this caused several potentially surprising results:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">a</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">pass</span>
<span class="n">c1</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">c2</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">c1</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">publish</span> <span class="o">=</span> <span class="mi">1</span>
<span class="c1"># c2.a.publish would now be == 1 also!</span>
</pre></div>
</div>
<p>Because a change to <code class="docutils literal notranslate"><span class="pre">a</span></code> bound <code class="docutils literal notranslate"><span class="pre">c1</span></code> also caused a change to
<code class="docutils literal notranslate"><span class="pre">a</span></code> bound to <code class="docutils literal notranslate"><span class="pre">c2</span></code>, setting of attributes on bound methods
was disallowed. However, even allowing setting of attributes on
unbound methods has its ambiguities:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">D</span><span class="p">(</span><span class="n">C</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span> <span class="nc">E</span><span class="p">(</span><span class="n">C</span><span class="p">):</span> <span class="k">pass</span>
<span class="n">D</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">publish</span> <span class="o">=</span> <span class="mi">1</span>
<span class="c1"># E.a.publish would now be == 1 also!</span>
</pre></div>
</div>
<p>For this reason, the current PEP disallows setting attributes on
either bound or unbound methods, but does allow for getting
attributes on either both return the attribute value on the
underlying function object.</p>
<p>A future PEP might propose to implement setting (bound or
unbound) method attributes by setting attributes on the instance
or class, using special naming conventions. I.e.:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">a</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">pass</span>
<span class="n">C</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">publish</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">C</span><span class="o">.</span><span class="n">__a_publish__</span> <span class="o">==</span> <span class="mi">1</span> <span class="c1"># true</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">c</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">publish</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">c</span><span class="o">.</span><span class="n">__a_publish__</span> <span class="o">==</span> <span class="mi">2</span> <span class="c1"># true</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">C</span><span class="p">()</span>
<span class="n">d</span><span class="o">.</span><span class="n">__a_publish__</span> <span class="o">==</span> <span class="mi">1</span> <span class="c1"># true</span>
</pre></div>
</div>
<p>Here, a lookup on the instance would look to the instances
dictionary first, followed by a lookup on the classs
dictionary, and finally a lookup on the function objects
dictionary.</p>
</li>
<li>Currently, Python supports function attributes only on Python
functions (i.e. those that are written in Python, not those that
are built-in). Should it be worthwhile, a separate patch can be
crafted that will add function attributes to built-ins.</li>
<li><code class="docutils literal notranslate"><span class="pre">__doc__</span></code> is the only function attribute that currently has
syntactic support for conveniently setting. It may be
worthwhile to eventually enhance the language for supporting
easy function attribute setting. Here are some syntaxes
suggested by PEP reviewers: <a class="footnote-reference brackets" href="#id6" id="id3">[3]</a><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">a</span> <span class="p">{</span>
<span class="s1">&#39;publish&#39;</span> <span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="s1">&#39;unittest&#39;</span><span class="p">:</span> <span class="s1">&#39;&#39;&#39;...&#39;&#39;&#39;</span><span class="p">,</span>
<span class="p">}</span>
<span class="p">(</span><span class="n">args</span><span class="p">):</span>
<span class="c1"># ...</span>
<span class="k">def</span> <span class="nf">a</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;The usual docstring.&quot;&quot;&quot;</span>
<span class="p">{</span><span class="s1">&#39;publish&#39;</span> <span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="s1">&#39;unittest&#39;</span><span class="p">:</span> <span class="s1">&#39;&#39;&#39;...&#39;&#39;&#39;</span><span class="p">,</span>
<span class="c1"># etc.</span>
<span class="p">}</span>
<span class="k">def</span> <span class="nf">a</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="n">having</span> <span class="p">(</span><span class="n">publish</span> <span class="o">=</span> <span class="mi">1</span><span class="p">):</span>
<span class="c1"># see reference [3]</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>The BDFL is currently against any such special syntactic support
for setting arbitrary function attributes. Any syntax proposals
would have to be outlined in new PEPs.</p>
</li>
</ul>
</section>
<section id="dissenting-opinion">
<h2><a class="toc-backref" href="#dissenting-opinion" role="doc-backlink">Dissenting Opinion</a></h2>
<p>When this was discussed on the python-dev mailing list in April
2000, a number of dissenting opinions were voiced. For
completeness, the discussion thread starts on <a class="reference external" href="https://mail.python.org/pipermail/python-dev/2000-April/003361.html">python-dev</a>.</p>
<p>The dissenting arguments appear to fall under the following
categories:</p>
<ul class="simple">
<li>no clear purpose (what does it buy you?)</li>
<li>other ways to do it (e.g. mappings as class attributes)</li>
<li>useless until syntactic support is included</li>
</ul>
<p>Countering some of these arguments is the observation that with
vanilla Python 2.0, <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> can in fact be set to any type of
object, so some semblance of writable function attributes are
already feasible. But that approach is yet another corruption of
<code class="docutils literal notranslate"><span class="pre">__doc__</span></code>.</p>
<p>And while it is of course possible to add mappings to class
objects (or in the case of function attributes, to the functions
module), it is more difficult and less obvious how to extract the
attribute values for inspection.</p>
<p>Finally, it may be desirable to add syntactic support, much the
same way that <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> syntactic support exists. This can be
considered separately from the ability to actually set and get
function attributes.</p>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
<p>This PEP has been accepted and the implementation has been
integrated into Python 2.1.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id4" role="doc-footnote">
<dt class="label" id="id4">[<a href="#id1">1</a>]</dt>
<dd>Aycock, “Compiling Little Languages in Python”,
<a class="reference external" href="https://legacy.python.org/workshops/1998-11/proceedings/papers/aycock-little/aycock-little.html">https://legacy.python.org/workshops/1998-11/proceedings/papers/aycock-little/aycock-little.html</a></aside>
<aside class="footnote brackets" id="id5" role="doc-footnote">
<dt class="label" id="id5">[<a href="#id2">2</a>]</dt>
<dd><a class="reference external" href="https://web.archive.org/web/20010307022153/http://classic.zope.org:8080/Documentation/Reference/ORB">https://web.archive.org/web/20010307022153/http://classic.zope.org:8080/Documentation/Reference/ORB</a></aside>
<aside class="footnote brackets" id="id6" role="doc-footnote">
<dt class="label" id="id6">[<a href="#id3">3</a>]</dt>
<dd>Hudson, Michael, SourceForge patch implementing this syntax,
<a class="reference external" href="https://web.archive.org/web/20010901050535/http://sourceforge.net/tracker/index.php?func=detail&amp;aid=403441&amp;group_id=5470&amp;atid=305470">https://web.archive.org/web/20010901050535/http://sourceforge.net/tracker/index.php?func=detail&amp;aid=403441&amp;group_id=5470&amp;atid=305470</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0232.rst">https://github.com/python/peps/blob/main/peps/pep-0232.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0232.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#examples">Examples</a><ul>
<li><a class="reference internal" href="#other-uses">Other Uses</a></li>
</ul>
</li>
<li><a class="reference internal" href="#future-directions">Future Directions</a></li>
<li><a class="reference internal" href="#dissenting-opinion">Dissenting Opinion</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0232.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

207
pep-0233/index.html Normal file
View File

@ -0,0 +1,207 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 233 Python Online Help | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0233/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 233 Python Online Help | peps.python.org'>
<meta property="og:description" content="This PEP describes a command-line driven online help facility for Python. The facility should be able to build on existing documentation facilities such as the Python documentation and docstrings. It should also be extensible for new types and modules.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0233/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP describes a command-line driven online help facility for Python. The facility should be able to build on existing documentation facilities such as the Python documentation and docstrings. It should also be extensible for new types and modules.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 233</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 233 Python Online Help</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Paul Prescod &lt;paul&#32;&#97;t&#32;prescod.net&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Inactive draft that may be taken up again at a later time">Deferred</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">11-Dec-2000</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#interactive-use">Interactive use</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#built-in-topics">Built-in Topics</a></li>
<li><a class="reference internal" href="#security-issues">Security Issues</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP describes a command-line driven online help facility for
Python. The facility should be able to build on existing
documentation facilities such as the Python documentation and
docstrings. It should also be extensible for new types and
modules.</p>
</section>
<section id="interactive-use">
<h2><a class="toc-backref" href="#interactive-use" role="doc-backlink">Interactive use</a></h2>
<p>Simply typing <code class="docutils literal notranslate"><span class="pre">help</span></code> describes the help function (through <code class="docutils literal notranslate"><span class="pre">repr()</span></code>
overloading).</p>
<p><code class="docutils literal notranslate"><span class="pre">help</span></code> can also be used as a function.</p>
<p>The function takes the following forms of input:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;string&quot;</span> <span class="pre">)</span></code> built-in topic or global</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&lt;ob&gt;</span> <span class="pre">)</span></code> docstring from object or type</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;doc:filename&quot;</span> <span class="pre">)</span></code> filename from Python documentation</li>
</ul>
<p>If you ask for a global, it can be a fully-qualified name, such as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">help</span><span class="p">(</span><span class="s2">&quot;xml.dom&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>You can also use the facility from a command-line:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">--</span><span class="n">help</span> <span class="k">if</span>
</pre></div>
</div>
<p>In either situation, the output does paging similar to the <code class="docutils literal notranslate"><span class="pre">more</span></code>
command.</p>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>The help function is implemented in an <code class="docutils literal notranslate"><span class="pre">onlinehelp</span></code> module which is
demand-loaded.</p>
<p>There should be options for fetching help information from
environments other than the command line through the <code class="docutils literal notranslate"><span class="pre">onlinehelp</span></code>
module:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">onlinehelp</span><span class="o">.</span><span class="n">gethelp</span><span class="p">(</span><span class="n">object_or_string</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">string</span>
</pre></div>
</div>
<p>It should also be possible to override the help display function
by assigning to <code class="docutils literal notranslate"><span class="pre">onlinehelp.displayhelp(object_or_string)</span></code>.</p>
<p>The module should be able to extract module information from
either the HTML or LaTeX versions of the Python documentation.
Links should be accommodated in a “lynx-like” manner.</p>
<p>Over time, it should also be able to recognize when docstrings are
in “special” syntaxes like structured text, HTML and LaTeX and
decode them appropriately.</p>
<p>A prototype implementation is available with the Python source
distribution as <code class="docutils literal notranslate"><span class="pre">nondist/sandbox/doctools/onlinehelp.py</span></code>.</p>
</section>
<section id="built-in-topics">
<h2><a class="toc-backref" href="#built-in-topics" role="doc-backlink">Built-in Topics</a></h2>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;intro&quot;</span> <span class="pre">)</span></code> What is Python? Read this first!</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;keywords&quot;</span> <span class="pre">)</span></code> What are the keywords?</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;syntax&quot;</span> <span class="pre">)</span></code> What is the overall syntax?</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;operators&quot;</span> <span class="pre">)</span></code> What operators are available?</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;builtins&quot;</span> <span class="pre">)</span></code> What functions, types, etc. are built-in?</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;modules&quot;</span> <span class="pre">)</span></code> What modules are in the standard library?</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;copyright&quot;</span> <span class="pre">)</span></code> Who owns Python?</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;moreinfo&quot;</span> <span class="pre">)</span></code> Where is there more information?</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;changes&quot;</span> <span class="pre">)</span></code> What changed in Python 2.0?</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;extensions&quot;</span> <span class="pre">)</span></code> What extensions are installed?</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;faq&quot;</span> <span class="pre">)</span></code> What questions are frequently asked?</li>
<li><code class="docutils literal notranslate"><span class="pre">help(</span> <span class="pre">&quot;ack&quot;</span> <span class="pre">)</span></code> Who has done work on Python lately?</li>
</ul>
</section>
<section id="security-issues">
<h2><a class="toc-backref" href="#security-issues" role="doc-backlink">Security Issues</a></h2>
<p>This module will attempt to import modules with the same names as
requested topics. Dont use the modules if you are not confident
that everything in your <code class="docutils literal notranslate"><span class="pre">PYTHONPATH</span></code> is from a trusted source.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0233.rst">https://github.com/python/peps/blob/main/peps/pep-0233.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0233.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#interactive-use">Interactive use</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#built-in-topics">Built-in Topics</a></li>
<li><a class="reference internal" href="#security-issues">Security Issues</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0233.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

531
pep-0234/index.html Normal file
View File

@ -0,0 +1,531 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 234 Iterators | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0234/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 234 Iterators | peps.python.org'>
<meta property="og:description" content="This document proposes an iteration interface that objects can provide to control the behaviour of for loops. Looping is customized by providing a method that produces an iterator object. The iterator provides a get next value operation that produces ...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0234/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This document proposes an iteration interface that objects can provide to control the behaviour of for loops. Looping is customized by providing a method that produces an iterator object. The iterator provides a get next value operation that produces ...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 234</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 234 Iterators</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Ka-Ping Yee &lt;ping&#32;&#97;t&#32;zesty.ca&gt;, Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">30-Jan-2001</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">30-Apr-2001</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#c-api-specification">C API Specification</a></li>
<li><a class="reference internal" href="#python-api-specification">Python API Specification</a></li>
<li><a class="reference internal" href="#dictionary-iterators">Dictionary Iterators</a></li>
<li><a class="reference internal" href="#file-iterators">File Iterators</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#resolved-issues">Resolved Issues</a></li>
<li><a class="reference internal" href="#mailing-lists">Mailing Lists</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This document proposes an iteration interface that objects can provide to
control the behaviour of <code class="docutils literal notranslate"><span class="pre">for</span></code> loops. Looping is customized by providing a
method that produces an iterator object. The iterator provides a <em>get next
value</em> operation that produces the next item in the sequence each time it is
called, raising an exception when no more items are available.</p>
<p>In addition, specific iterators over the keys of a dictionary and over the
lines of a file are proposed, and a proposal is made to allow spelling
<code class="docutils literal notranslate"><span class="pre">dict.has_key(key)</span></code> as <code class="docutils literal notranslate"><span class="pre">key</span> <span class="pre">in</span> <span class="pre">dict</span></code>.</p>
<p>Note: this is an almost complete rewrite of this PEP by the second author,
describing the actual implementation checked into the trunk of the Python 2.2
CVS tree. It is still open for discussion. Some of the more esoteric
proposals in the original version of this PEP have been withdrawn for now;
these may be the subject of a separate PEP in the future.</p>
</section>
<section id="c-api-specification">
<h2><a class="toc-backref" href="#c-api-specification" role="doc-backlink">C API Specification</a></h2>
<p>A new exception is defined, <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code>, which can be used to signal the
end of an iteration.</p>
<p>A new slot named <code class="docutils literal notranslate"><span class="pre">tp_iter</span></code> for requesting an iterator is added to the type
object structure. This should be a function of one <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code> argument
returning a <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code>, or <code class="docutils literal notranslate"><span class="pre">NULL</span></code>. To use this slot, a new C API
function <code class="docutils literal notranslate"><span class="pre">PyObject_GetIter()</span></code> is added, with the same signature as the
<code class="docutils literal notranslate"><span class="pre">tp_iter</span></code> slot function.</p>
<p>Another new slot, named <code class="docutils literal notranslate"><span class="pre">tp_iternext</span></code>, is added to the type structure, for
obtaining the next value in the iteration. To use this slot, a new C API
function <code class="docutils literal notranslate"><span class="pre">PyIter_Next()</span></code> is added. The signature for both the slot and the
API function is as follows, although the <code class="docutils literal notranslate"><span class="pre">NULL</span></code> return conditions differ:
the argument is a <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code> and so is the return value. When the return
value is non-<code class="docutils literal notranslate"><span class="pre">NULL</span></code>, it is the next value in the iteration. When it is
<code class="docutils literal notranslate"><span class="pre">NULL</span></code>, then for the <code class="docutils literal notranslate"><span class="pre">tp_iternext</span> <span class="pre">slot</span></code> there are three possibilities:</p>
<ul class="simple">
<li>No exception is set; this implies the end of the iteration.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> exception (or a derived exception class) is set; this
implies the end of the iteration.</li>
<li>Some other exception is set; this means that an error occurred that should be
propagated normally.</li>
</ul>
<p>The higher-level <code class="docutils literal notranslate"><span class="pre">PyIter_Next()</span></code> function clears the <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code>
exception (or derived exception) when it occurs, so its <code class="docutils literal notranslate"><span class="pre">NULL</span></code> return
conditions are simpler:</p>
<ul class="simple">
<li>No exception is set; this means iteration has ended.</li>
<li>Some exception is set; this means an error occurred, and should be propagated
normally.</li>
</ul>
<p>Iterators implemented in C should <em>not</em> implement a <code class="docutils literal notranslate"><span class="pre">next()</span></code> method with
similar semantics as the <code class="docutils literal notranslate"><span class="pre">tp_iternext</span></code> slot! When the types dictionary is
initialized (by <code class="docutils literal notranslate"><span class="pre">PyType_Ready()</span></code>), the presence of a <code class="docutils literal notranslate"><span class="pre">tp_iternext</span></code> slot
causes a method <code class="docutils literal notranslate"><span class="pre">next()</span></code> wrapping that slot to be added to the types
<code class="docutils literal notranslate"><span class="pre">tp_dict</span></code>. (Exception: if the type doesnt use <code class="docutils literal notranslate"><span class="pre">PyObject_GenericGetAttr()</span></code>
to access instance attributes, the <code class="docutils literal notranslate"><span class="pre">next()</span></code> method in the types <code class="docutils literal notranslate"><span class="pre">tp_dict</span></code>
may not be seen.) (Due to a misunderstanding in the original text of this PEP,
in Python 2.2, all iterator types implemented a <code class="docutils literal notranslate"><span class="pre">next()</span></code> method that was
overridden by the wrapper; this has been fixed in Python 2.3.)</p>
<p>To ensure binary backwards compatibility, a new flag <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_ITER</span></code>
is added to the set of flags in the <code class="docutils literal notranslate"><span class="pre">tp_flags</span></code> field, and to the default
flags macro. This flag must be tested before accessing the <code class="docutils literal notranslate"><span class="pre">tp_iter</span></code> or
<code class="docutils literal notranslate"><span class="pre">tp_iternext</span></code> slots. The macro <code class="docutils literal notranslate"><span class="pre">PyIter_Check()</span></code> tests whether an object
has the appropriate flag set and has a non-<code class="docutils literal notranslate"><span class="pre">NULL</span></code> <code class="docutils literal notranslate"><span class="pre">tp_iternext</span></code> slot.
There is no such macro for the <code class="docutils literal notranslate"><span class="pre">tp_iter</span></code> slot (since the only place where
this slot is referenced should be <code class="docutils literal notranslate"><span class="pre">PyObject_GetIter()</span></code>, and this can check
for the <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_ITER</span></code> flag directly).</p>
<p>(Note: the <code class="docutils literal notranslate"><span class="pre">tp_iter</span></code> slot can be present on any object; the <code class="docutils literal notranslate"><span class="pre">tp_iternext</span></code>
slot should only be present on objects that act as iterators.)</p>
<p>For backwards compatibility, the <code class="docutils literal notranslate"><span class="pre">PyObject_GetIter()</span></code> function implements
fallback semantics when its argument is a sequence that does not implement a
<code class="docutils literal notranslate"><span class="pre">tp_iter</span></code> function: a lightweight sequence iterator object is constructed in
that case which iterates over the items of the sequence in the natural order.</p>
<p>The Python bytecode generated for <code class="docutils literal notranslate"><span class="pre">for</span></code> loops is changed to use new opcodes,
<code class="docutils literal notranslate"><span class="pre">GET_ITER</span></code> and <code class="docutils literal notranslate"><span class="pre">FOR_ITER</span></code>, that use the iterator protocol rather than the
sequence protocol to get the next value for the loop variable. This makes it
possible to use a <code class="docutils literal notranslate"><span class="pre">for</span></code> loop to loop over non-sequence objects that support
the <code class="docutils literal notranslate"><span class="pre">tp_iter</span></code> slot. Other places where the interpreter loops over the values
of a sequence should also be changed to use iterators.</p>
<p>Iterators ought to implement the <code class="docutils literal notranslate"><span class="pre">tp_iter</span></code> slot as returning a reference to
themselves; this is needed to make it possible to use an iterator (as opposed
to a sequence) in a <code class="docutils literal notranslate"><span class="pre">for</span></code> loop.</p>
<p>Iterator implementations (in C or in Python) should guarantee that once the
iterator has signalled its exhaustion, subsequent calls to <code class="docutils literal notranslate"><span class="pre">tp_iternext</span></code> or
to the <code class="docutils literal notranslate"><span class="pre">next()</span></code> method will continue to do so. It is not specified whether
an iterator should enter the exhausted state when an exception (other than
<code class="docutils literal notranslate"><span class="pre">StopIteration</span></code>) is raised. Note that Python cannot guarantee that
user-defined or 3rd party iterators implement this requirement correctly.</p>
</section>
<section id="python-api-specification">
<h2><a class="toc-backref" href="#python-api-specification" role="doc-backlink">Python API Specification</a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> exception is made visible as one of the standard
exceptions. It is derived from <code class="docutils literal notranslate"><span class="pre">Exception</span></code>.</p>
<p>A new built-in function is defined, <code class="docutils literal notranslate"><span class="pre">iter()</span></code>, which can be called in two
ways:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">iter(obj)</span></code> calls <code class="docutils literal notranslate"><span class="pre">PyObject_GetIter(obj)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">iter(callable,</span> <span class="pre">sentinel)</span></code> returns a special kind of iterator that calls
the callable to produce a new value, and compares the return value to the
sentinel value. If the return value equals the sentinel, this signals the
end of the iteration and <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> is raised rather than returning
normal; if the return value does not equal the sentinel, it is returned as
the next value from the iterator. If the callable raises an exception, this
is propagated normally; in particular, the function is allowed to raise
<code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> as an alternative way to end the iteration. (This
functionality is available from the C API as
<code class="docutils literal notranslate"><span class="pre">PyCallIter_New(callable,</span> <span class="pre">sentinel)</span></code>.)</li>
</ul>
<p>Iterator objects returned by either form of <code class="docutils literal notranslate"><span class="pre">iter()</span></code> have a <code class="docutils literal notranslate"><span class="pre">next()</span></code>
method. This method either returns the next value in the iteration, or raises
<code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> (or a derived exception class) to signal the end of the
iteration. Any other exception should be considered to signify an error and
should be propagated normally, not taken to mean the end of the iteration.</p>
<p>Classes can define how they are iterated over by defining an <code class="docutils literal notranslate"><span class="pre">__iter__()</span></code>
method; this should take no additional arguments and return a valid iterator
object. A class that wants to be an iterator should implement two methods: a
<code class="docutils literal notranslate"><span class="pre">next()</span></code> method that behaves as described above, and an <code class="docutils literal notranslate"><span class="pre">__iter__()</span></code> method
that returns <code class="docutils literal notranslate"><span class="pre">self</span></code>.</p>
<p>The two methods correspond to two distinct protocols:</p>
<ol class="arabic simple">
<li>An object can be iterated over with <code class="docutils literal notranslate"><span class="pre">for</span></code> if it implements <code class="docutils literal notranslate"><span class="pre">__iter__()</span></code>
or <code class="docutils literal notranslate"><span class="pre">__getitem__()</span></code>.</li>
<li>An object can function as an iterator if it implements <code class="docutils literal notranslate"><span class="pre">next()</span></code>.</li>
</ol>
<p>Container-like objects usually support protocol 1. Iterators are currently
required to support both protocols. The semantics of iteration come only from
protocol 2; protocol 1 is present to make iterators behave like sequences; in
particular so that code receiving an iterator can use a for-loop over the
iterator.</p>
</section>
<section id="dictionary-iterators">
<h2><a class="toc-backref" href="#dictionary-iterators" role="doc-backlink">Dictionary Iterators</a></h2>
<ul>
<li>Dictionaries implement a <code class="docutils literal notranslate"><span class="pre">sq_contains</span></code> slot that implements the same test
as the <code class="docutils literal notranslate"><span class="pre">has_key()</span></code> method. This means that we can write<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">dict</span><span class="p">:</span> <span class="o">...</span>
</pre></div>
</div>
<p>which is equivalent to</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="nb">dict</span><span class="o">.</span><span class="n">has_key</span><span class="p">(</span><span class="n">k</span><span class="p">):</span> <span class="o">...</span>
</pre></div>
</div>
</li>
<li>Dictionaries implement a <code class="docutils literal notranslate"><span class="pre">tp_iter</span></code> slot that returns an efficient iterator
that iterates over the keys of the dictionary. During such an iteration, the
dictionary should not be modified, except that setting the value for an
existing key is allowed (deletions or additions are not, nor is the
<code class="docutils literal notranslate"><span class="pre">update()</span></code> method). This means that we can write<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">dict</span><span class="p">:</span> <span class="o">...</span>
</pre></div>
</div>
<p>which is equivalent to, but much faster than</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">dict</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span> <span class="o">...</span>
</pre></div>
</div>
<p>as long as the restriction on modifications to the dictionary (either by the
loop or by another thread) are not violated.</p>
</li>
<li>Add methods to dictionaries that return different kinds of iterators
explicitly:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="nb">dict</span><span class="o">.</span><span class="n">iterkeys</span><span class="p">():</span> <span class="o">...</span>
<span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">dict</span><span class="o">.</span><span class="n">itervalues</span><span class="p">():</span> <span class="o">...</span>
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">dict</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span> <span class="o">...</span>
</pre></div>
</div>
<p>This means that <code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">dict</span></code> is shorthand for
<code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">dict.iterkeys()</span></code>.</p>
</li>
</ul>
<p>Other mappings, if they support iterators at all, should also iterate over the
keys. However, this should not be taken as an absolute rule; specific
applications may have different requirements.</p>
</section>
<section id="file-iterators">
<h2><a class="toc-backref" href="#file-iterators" role="doc-backlink">File Iterators</a></h2>
<p>The following proposal is useful because it provides us with a good answer to
the complaint that the common idiom to iterate over the lines of a file is ugly
and slow.</p>
<ul>
<li>Files implement a <code class="docutils literal notranslate"><span class="pre">tp_iter</span></code> slot that is equivalent to
<code class="docutils literal notranslate"><span class="pre">iter(f.readline,</span> <span class="pre">&quot;&quot;)</span></code>. This means that we can write<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">file</span><span class="p">:</span>
<span class="o">...</span>
</pre></div>
</div>
<p>as a shorthand for</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">iter</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">readline</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">):</span>
<span class="o">...</span>
</pre></div>
</div>
<p>which is equivalent to, but faster than</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">file</span><span class="o">.</span><span class="n">readline</span><span class="p">()</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">line</span><span class="p">:</span>
<span class="k">break</span>
<span class="o">...</span>
</pre></div>
</div>
</li>
</ul>
<p>This also shows that some iterators are destructive: they consume all the
values and a second iterator cannot easily be created that iterates
independently over the same values. You could open the file for a second time,
or <code class="docutils literal notranslate"><span class="pre">seek()</span></code> to the beginning, but these solutions dont work for all file
types, e.g. they dont work when the open file object really represents a pipe
or a stream socket.</p>
<p>Because the file iterator uses an internal buffer, mixing this with other file
operations (e.g. <code class="docutils literal notranslate"><span class="pre">file.readline()</span></code>) doesnt work right. Also, the following
code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">file</span><span class="p">:</span>
<span class="k">if</span> <span class="n">line</span> <span class="o">==</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">file</span><span class="p">:</span>
<span class="nb">print</span> <span class="n">line</span><span class="p">,</span>
</pre></div>
</div>
<p>doesnt work as you might expect, because the iterator created by the second
for-loop doesnt take the buffer read-ahead by the first for-loop into account.
A correct way to write this is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">it</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">it</span><span class="p">:</span>
<span class="k">if</span> <span class="n">line</span> <span class="o">==</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">it</span><span class="p">:</span>
<span class="nb">print</span> <span class="n">line</span><span class="p">,</span>
</pre></div>
</div>
<p>(The rationale for these restrictions are that <code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">line</span> <span class="pre">in</span> <span class="pre">file</span></code> ought to
become the recommended, standard way to iterate over the lines of a file, and
this should be as fast as can be. The iterator version is considerable faster
than calling <code class="docutils literal notranslate"><span class="pre">readline()</span></code>, due to the internal buffer in the iterator.)</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>If all the parts of the proposal are included, this addresses many concerns in
a consistent and flexible fashion. Among its chief virtues are the following
four no, five no, six points:</p>
<ol class="arabic simple">
<li>It provides an extensible iterator interface.</li>
<li>It allows performance enhancements to list iteration.</li>
<li>It allows big performance enhancements to dictionary iteration.</li>
<li>It allows one to provide an interface for just iteration without pretending
to provide random access to elements.</li>
<li>It is backward-compatible with all existing user-defined classes and
extension objects that emulate sequences and mappings, even mappings that
only implement a subset of {<code class="docutils literal notranslate"><span class="pre">__getitem__</span></code>, <code class="docutils literal notranslate"><span class="pre">keys</span></code>, <code class="docutils literal notranslate"><span class="pre">values</span></code>,
<code class="docutils literal notranslate"><span class="pre">items</span></code>}.</li>
<li>It makes code iterating over non-sequence collections more concise and
readable.</li>
</ol>
</section>
<section id="resolved-issues">
<h2><a class="toc-backref" href="#resolved-issues" role="doc-backlink">Resolved Issues</a></h2>
<p>The following topics have been decided by consensus or BDFL pronouncement.</p>
<ul>
<li>Two alternative spellings for <code class="docutils literal notranslate"><span class="pre">next()</span></code> have been proposed but rejected:
<code class="docutils literal notranslate"><span class="pre">__next__()</span></code>, because it corresponds to a type object slot
(<code class="docutils literal notranslate"><span class="pre">tp_iternext</span></code>); and <code class="docutils literal notranslate"><span class="pre">__call__()</span></code>, because this is the only operation.<p>Arguments against <code class="docutils literal notranslate"><span class="pre">__next__()</span></code>: while many iterators are used in for loops,
it is expected that user code will also call <code class="docutils literal notranslate"><span class="pre">next()</span></code> directly, so having
to write <code class="docutils literal notranslate"><span class="pre">__next__()</span></code> is ugly; also, a possible extension of the protocol
would be to allow for <code class="docutils literal notranslate"><span class="pre">prev()</span></code>, <code class="docutils literal notranslate"><span class="pre">current()</span></code> and <code class="docutils literal notranslate"><span class="pre">reset()</span></code> operations;
surely we dont want to use <code class="docutils literal notranslate"><span class="pre">__prev__()</span></code>, <code class="docutils literal notranslate"><span class="pre">__current__()</span></code>,
<code class="docutils literal notranslate"><span class="pre">__reset__()</span></code>.</p>
<p>Arguments against <code class="docutils literal notranslate"><span class="pre">__call__()</span></code> (the original proposal): taken out of
context, <code class="docutils literal notranslate"><span class="pre">x()</span></code> is not very readable, while <code class="docutils literal notranslate"><span class="pre">x.next()</span></code> is clear; theres a
danger that every special-purpose object wants to use <code class="docutils literal notranslate"><span class="pre">__call__()</span></code> for its
most common operation, causing more confusion than clarity.</p>
<p>(In retrospect, it might have been better to go for <code class="docutils literal notranslate"><span class="pre">__next__()</span></code> and have a
new built-in, <code class="docutils literal notranslate"><span class="pre">next(it)</span></code>, which calls <code class="docutils literal notranslate"><span class="pre">it.__next__()</span></code>. But alas, its too
late; this has been deployed in Python 2.2 since December 2001.)</p>
</li>
<li>Some folks have requested the ability to restart an iterator. This should be
dealt with by calling <code class="docutils literal notranslate"><span class="pre">iter()</span></code> on a sequence repeatedly, not by the
iterator protocol itself. (See also requested extensions below.)</li>
<li>It has been questioned whether an exception to signal the end of the
iteration isnt too expensive. Several alternatives for the
<code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> exception have been proposed: a special value <code class="docutils literal notranslate"><span class="pre">End</span></code> to
signal the end, a function <code class="docutils literal notranslate"><span class="pre">end()</span></code> to test whether the iterator is
finished, even reusing the <code class="docutils literal notranslate"><span class="pre">IndexError</span></code> exception.<ul class="simple">
<li>A special value has the problem that if a sequence ever contains that
special value, a loop over that sequence will end prematurely without any
warning. If the experience with null-terminated C strings hasnt taught us
the problems this can cause, imagine the trouble a Python introspection
tool would have iterating over a list of all built-in names, assuming that
the special <code class="docutils literal notranslate"><span class="pre">End</span></code> value was a built-in name!</li>
<li>Calling an <code class="docutils literal notranslate"><span class="pre">end()</span></code> function would require two calls per iteration. Two
calls is much more expensive than one call plus a test for an exception.
Especially the time-critical for loop can test very cheaply for an
exception.</li>
<li>Reusing <code class="docutils literal notranslate"><span class="pre">IndexError</span></code> can cause confusion because it can be a genuine
error, which would be masked by ending the loop prematurely.</li>
</ul>
</li>
<li>Some have asked for a standard iterator type. Presumably all iterators would
have to be derived from this type. But this is not the Python way:
dictionaries are mappings because they support <code class="docutils literal notranslate"><span class="pre">__getitem__()</span></code> and a
handful other operations, not because they are derived from an abstract
mapping type.</li>
<li>Regarding <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">key</span> <span class="pre">in</span> <span class="pre">dict</span></code>: there is no doubt that the <code class="docutils literal notranslate"><span class="pre">dict.has_key(x)</span></code>
interpretation of <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">in</span> <span class="pre">dict</span></code> is by far the most useful interpretation,
probably the only useful one. There has been resistance against this because
<code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">in</span> <span class="pre">list</span></code> checks whether <em>x</em> is present among the values, while the
proposal makes <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">in</span> <span class="pre">dict</span></code> check whether <em>x</em> is present among the keys.
Given that the symmetry between lists and dictionaries is very weak, this
argument does not have much weight.</li>
<li>The name <code class="docutils literal notranslate"><span class="pre">iter()</span></code> is an abbreviation. Alternatives proposed include
<code class="docutils literal notranslate"><span class="pre">iterate()</span></code>, <code class="docutils literal notranslate"><span class="pre">traverse()</span></code>, but these appear too long. Python has a
history of using abbrs for common builtins, e.g. <code class="docutils literal notranslate"><span class="pre">repr()</span></code>, <code class="docutils literal notranslate"><span class="pre">str()</span></code>,
<code class="docutils literal notranslate"><span class="pre">len()</span></code>.<p>Resolution: <code class="docutils literal notranslate"><span class="pre">iter()</span></code> it is.</p>
</li>
<li>Using the same name for two different operations (getting an iterator from an
object and making an iterator for a function with a sentinel value) is
somewhat ugly. I havent seen a better name for the second operation though,
and since they both return an iterator, its easy to remember.<p>Resolution: the builtin <code class="docutils literal notranslate"><span class="pre">iter()</span></code> takes an optional argument, which is the
sentinel to look for.</p>
</li>
<li>Once a particular iterator object has raised <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code>, will it also
raise <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> on all subsequent <code class="docutils literal notranslate"><span class="pre">next()</span></code> calls? Some say that it
would be useful to require this, others say that it is useful to leave this
open to individual iterators. Note that this may require an additional state
bit for some iterator implementations (e.g. function-wrapping iterators).<p>Resolution: once <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> is raised, calling <code class="docutils literal notranslate"><span class="pre">it.next()</span></code> continues
to raise <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code>.</p>
<p>Note: this was in fact not implemented in Python 2.2; there are many cases
where an iterators <code class="docutils literal notranslate"><span class="pre">next()</span></code> method can raise <code class="docutils literal notranslate"><span class="pre">StopIteration</span></code> on one call
but not on the next. This has been remedied in Python 2.3.</p>
</li>
<li>It has been proposed that a file object should be its own iterator, with a
<code class="docutils literal notranslate"><span class="pre">next()</span></code> method returning the next line. This has certain advantages, and
makes it even clearer that this iterator is destructive. The disadvantage is
that this would make it even more painful to implement the “sticky
StopIteration” feature proposed in the previous bullet.<p>Resolution: tentatively rejected (though there are still people arguing for
this).</p>
</li>
<li>Some folks have requested extensions of the iterator protocol, e.g.
<code class="docutils literal notranslate"><span class="pre">prev()</span></code> to get the previous item, <code class="docutils literal notranslate"><span class="pre">current()</span></code> to get the current item
again, <code class="docutils literal notranslate"><span class="pre">finished()</span></code> to test whether the iterator is finished, and maybe
even others, like <code class="docutils literal notranslate"><span class="pre">rewind()</span></code>, <code class="docutils literal notranslate"><span class="pre">__len__()</span></code>, <code class="docutils literal notranslate"><span class="pre">position()</span></code>.<p>While some of these are useful, many of these cannot easily be implemented
for all iterator types without adding arbitrary buffering, and sometimes they
cant be implemented at all (or not reasonably). E.g. anything to do with
reversing directions cant be done when iterating over a file or function.
Maybe a separate PEP can be drafted to standardize the names for such
operations when they are implementable.</p>
<p>Resolution: rejected.</p>
</li>
<li>There has been a long discussion about whether<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">dict</span><span class="p">:</span> <span class="o">...</span>
</pre></div>
</div>
<p>should assign <em>x</em> the successive keys, values, or items of the dictionary.
The symmetry between <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">y</span></code> and <code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">y</span></code> suggests that it should
iterate over keys. This symmetry has been observed by many independently and
has even been used to “explain” one using the other. This is because for
sequences, <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">y</span></code> iterates over <em>y</em> comparing the iterated values to
<em>x</em>. If we adopt both of the above proposals, this will also hold for
dictionaries.</p>
<p>The argument against making <code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">dict</span></code> iterate over the keys comes
mostly from a practicality point of view: scans of the standard library show
that there are about as many uses of <code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">dict.items()</span></code> as there are
of <code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">dict.keys()</span></code>, with the <code class="docutils literal notranslate"><span class="pre">items()</span></code> version having a small
majority. Presumably many of the loops using <code class="docutils literal notranslate"><span class="pre">keys()</span></code> use the
corresponding value anyway, by writing <code class="docutils literal notranslate"><span class="pre">dict[x]</span></code>, so (the argument goes) by
making both the key and value available, we could support the largest number
of cases. While this is true, I (Guido) find the correspondence between
<code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">dict</span></code> and <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">dict</span></code> too compelling to break, and theres
not much overhead in having to write <code class="docutils literal notranslate"><span class="pre">dict[x]</span></code> to explicitly get the value.</p>
<p>For fast iteration over items, use <code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">key,</span> <span class="pre">value</span> <span class="pre">in</span> <span class="pre">dict.iteritems()</span></code>.
Ive timed the difference between</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="nb">dict</span><span class="p">:</span> <span class="nb">dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
</pre></div>
</div>
<p>and</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">dict</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span> <span class="k">pass</span>
</pre></div>
</div>
<p>and found that the latter is only about 7% faster.</p>
<p>Resolution: By BDFL pronouncement, <code class="docutils literal notranslate"><span class="pre">for</span> <span class="pre">x</span> <span class="pre">in</span> <span class="pre">dict</span></code> iterates over the keys,
and dictionaries have <code class="docutils literal notranslate"><span class="pre">iteritems()</span></code>, <code class="docutils literal notranslate"><span class="pre">iterkeys()</span></code>, and <code class="docutils literal notranslate"><span class="pre">itervalues()</span></code>
to return the different flavors of dictionary iterators.</p>
</li>
</ul>
</section>
<section id="mailing-lists">
<h2><a class="toc-backref" href="#mailing-lists" role="doc-backlink">Mailing Lists</a></h2>
<p>The iterator protocol has been discussed extensively in a mailing list on
SourceForge:</p>
<blockquote>
<div><a class="reference external" href="http://lists.sourceforge.net/lists/listinfo/python-iterators">http://lists.sourceforge.net/lists/listinfo/python-iterators</a></div></blockquote>
<p>Initially, some of the discussion was carried out at Yahoo; archives are still
accessible:</p>
<blockquote>
<div><a class="reference external" href="http://groups.yahoo.com/group/python-iter">http://groups.yahoo.com/group/python-iter</a></div></blockquote>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document is in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0234.rst">https://github.com/python/peps/blob/main/peps/pep-0234.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0234.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#c-api-specification">C API Specification</a></li>
<li><a class="reference internal" href="#python-api-specification">Python API Specification</a></li>
<li><a class="reference internal" href="#dictionary-iterators">Dictionary Iterators</a></li>
<li><a class="reference internal" href="#file-iterators">File Iterators</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#resolved-issues">Resolved Issues</a></li>
<li><a class="reference internal" href="#mailing-lists">Mailing Lists</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0234.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

252
pep-0235/index.html Normal file
View File

@ -0,0 +1,252 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 235 Import on Case-Insensitive Platforms | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0235/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 235 Import on Case-Insensitive Platforms | peps.python.org'>
<meta property="og:description" content="Python Enhancement Proposals (PEPs)">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0235/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python Enhancement Proposals (PEPs)">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 235</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 235 Import on Case-Insensitive Platforms</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Tim Peters &lt;tim.peters&#32;&#97;t&#32;gmail.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">21-Feb-2001</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">16-Feb-2001</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#note">Note</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#current-lower-left-semantics">Current Lower-Left Semantics</a></li>
<li><a class="reference internal" href="#proposed-semantics">Proposed Semantics</a></li>
</ul>
</details></section>
<section id="note">
<h2><a class="toc-backref" href="#note" role="doc-backlink">Note</a></h2>
<p>This is essentially a retroactive PEP: the issue came up too late
in the 2.1 release process to solicit wide opinion before deciding
what to do, and cant be put off until 2.2 without also delaying
the Cygwin and MacOS X ports.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>File systems vary across platforms in whether or not they preserve
the case of filenames, and in whether or not the platform C
library file-opening functions do or dont insist on
case-sensitive matches:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="k">case</span><span class="o">-</span><span class="n">preserving</span> <span class="n">case</span><span class="o">-</span><span class="n">destroying</span>
<span class="o">+-------------------+------------------+</span>
<span class="k">case</span><span class="o">-</span><span class="n">sensitive</span> <span class="o">|</span> <span class="n">most</span> <span class="n">Unix</span> <span class="n">flavors</span> <span class="o">|</span> <span class="n">brrrrrrrrrr</span> <span class="o">|</span>
<span class="o">+-------------------+------------------+</span>
<span class="k">case</span><span class="o">-</span><span class="n">insensitive</span> <span class="o">|</span> <span class="n">Windows</span> <span class="o">|</span> <span class="n">some</span> <span class="n">unfortunate</span> <span class="o">|</span>
<span class="o">|</span> <span class="n">MacOSX</span> <span class="n">HFS</span><span class="o">+</span> <span class="o">|</span> <span class="n">network</span> <span class="n">schemes</span> <span class="o">|</span>
<span class="o">|</span> <span class="n">Cygwin</span> <span class="o">|</span> <span class="o">|</span>
<span class="o">|</span> <span class="o">|</span> <span class="n">OpenVMS</span> <span class="o">|</span>
<span class="o">+-------------------+------------------+</span>
</pre></div>
</div>
<p>In the upper left box, if you create “fiLe” its stored as “fiLe”,
and only <code class="docutils literal notranslate"><span class="pre">open(&quot;fiLe&quot;)</span></code> will open it (<code class="docutils literal notranslate"><span class="pre">open(&quot;file&quot;)</span></code> will not, nor
will the 14 other variations on that theme).</p>
<p>In the lower right box, if you create “fiLe”, theres no telling
what its stored as but most likely as “FILE” and any of the
16 obvious variations on <code class="docutils literal notranslate"><span class="pre">open(&quot;FilE&quot;)</span></code> will open it.</p>
<p>The lower left box is a mix: creating “fiLe” stores “fiLe” in the
platform directory, but you dont have to match case when opening
it; any of the 16 obvious variations on <code class="docutils literal notranslate"><span class="pre">open(&quot;FILe&quot;)</span></code> work.</p>
<p>NONE OF THAT IS CHANGING! Python will continue to follow platform
conventions w.r.t. whether case is preserved when creating a file,
and w.r.t. whether <code class="docutils literal notranslate"><span class="pre">open()</span></code> requires a case-sensitive match. In
practice, you should always code as if matches were
case-sensitive, else your program wont be portable.</p>
<p>Whats proposed is to change the semantics of Python “import”
statements, and there <em>only</em> in the lower left box.</p>
</section>
<section id="current-lower-left-semantics">
<h2><a class="toc-backref" href="#current-lower-left-semantics" role="doc-backlink">Current Lower-Left Semantics</a></h2>
<p>Support for MacOSX HFS+, and for Cygwin, is new in 2.1, so nothing
is changing there. Whats changing is Windows behavior. Here are
the current rules for import on Windows:</p>
<ol class="arabic">
<li>Despite that the filesystem is case-insensitive, Python insists
on a case-sensitive match. But not in the way the upper left
box works: if you have two files, <code class="docutils literal notranslate"><span class="pre">FiLe.py</span></code> and <code class="docutils literal notranslate"><span class="pre">file.py</span></code> on
<code class="docutils literal notranslate"><span class="pre">sys.path</span></code>, and do<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">file</span>
</pre></div>
</div>
<p>then if Python finds <code class="docutils literal notranslate"><span class="pre">FiLe.py</span></code> first, it raises a <code class="docutils literal notranslate"><span class="pre">NameError</span></code>.
It does <em>not</em> go on to find <code class="docutils literal notranslate"><span class="pre">file.py</span></code>; indeed, its impossible to
import any but the first case-insensitive match on <code class="docutils literal notranslate"><span class="pre">sys.path</span></code>,
and then only if case matches exactly in the first
case-insensitive match.</p>
</li>
<li>An ugly exception: if the first case-insensitive match on
<code class="docutils literal notranslate"><span class="pre">sys.path</span></code> is for a file whose name is entirely in upper case
(<code class="docutils literal notranslate"><span class="pre">FILE.PY</span></code> or <code class="docutils literal notranslate"><span class="pre">FILE.PYC</span></code> or <code class="docutils literal notranslate"><span class="pre">FILE.PYO</span></code>), then the import silently
grabs that, no matter what mixture of case was used in the
import statement. This is apparently to cater to miserable old
filesystems that really fit in the lower right box. But this
exception is unique to Windows, for reasons that may or may not
exist.</li>
<li>And another exception: if the environment variable <code class="docutils literal notranslate"><span class="pre">PYTHONCASEOK</span></code>
exists, Python silently grabs the first case-insensitive match
of any kind.</li>
</ol>
<p>So these Windows rules are pretty complicated, and neither match
the Unix rules nor provide semantics natural for the native
filesystem. That makes them hard to explain to Unix <em>or</em> Windows
users. Nevertheless, theyve worked fine for years, and in
isolation theres no compelling reason to change them.</p>
<p>However, that was before the MacOSX HFS+ and Cygwin ports arrived.
They also have case-preserving case-insensitive filesystems, but
the people doing the ports despised the Windows rules. Indeed, a
patch to make HFS+ act like Unix for imports got past a reviewer
and into the code base, which incidentally made Cygwin also act
like Unix (but this met the unbounded approval of the Cygwin
folks, so they sure didnt complain they had patches of their
own pending to do this, but the reviewer for those balked).</p>
<p>At a higher level, we want to keep Python consistent, by following
the same rules on <em>all</em> platforms with case-preserving
case-insensitive filesystems.</p>
</section>
<section id="proposed-semantics">
<h2><a class="toc-backref" href="#proposed-semantics" role="doc-backlink">Proposed Semantics</a></h2>
<p>The proposed new semantics for the lower left box:</p>
<ol class="upperalpha simple">
<li>If the <code class="docutils literal notranslate"><span class="pre">PYTHONCASEOK</span></code> environment variable exists, same as
before: silently accept the first case-insensitive match of any
kind; raise <code class="docutils literal notranslate"><span class="pre">ImportError</span></code> if none found.</li>
<li>Else search <code class="docutils literal notranslate"><span class="pre">sys.path</span></code> for the first case-sensitive match; raise
<code class="docutils literal notranslate"><span class="pre">ImportError</span></code> if none found.</li>
</ol>
<p>#B is the same rule as is used on Unix, so this will improve
cross-platform portability. Thats good. #B is also the rule the Mac
and Cygwin folks want (and wanted enough to implement themselves,
multiple times, which is a powerful argument in PythonLand). It
cant cause any existing non-exceptional Windows import to fail,
because any existing non-exceptional Windows import finds a
case-sensitive match first in the path and it still will. An
exceptional Windows import currently blows up with a <code class="docutils literal notranslate"><span class="pre">NameError</span></code> or
<code class="docutils literal notranslate"><span class="pre">ImportError</span></code>, in which latter case it still will, or in which
former case will continue searching, and either succeed or blow up
with an <code class="docutils literal notranslate"><span class="pre">ImportError</span></code>.</p>
<p>#A is needed to cater to case-destroying filesystems mounted on Windows,
and <em>may</em> also be used by people so enamored of “natural” Windows
behavior that theyre willing to set an environment variable to
get it. I dont intend to implement #A for Unix too, but thats
just because Im not clear on how I <em>could</em> do so efficiently (Im
not going to slow imports under Unix just for theoretical purity).</p>
<p>The potential damage is here: #2 (matching on <code class="docutils literal notranslate"><span class="pre">ALLCAPS.PY</span></code>) is
proposed to be dropped. Case-destroying filesystems are a
vanishing breed, and support for them is ugly. Were already
supporting (and will continue to support) <code class="docutils literal notranslate"><span class="pre">PYTHONCASEOK</span></code> for their
benefit, but they dont deserve multiple hacks in 2001.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0235.rst">https://github.com/python/peps/blob/main/peps/pep-0235.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0235.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#note">Note</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#current-lower-left-semantics">Current Lower-Left Semantics</a></li>
<li><a class="reference internal" href="#proposed-semantics">Proposed Semantics</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0235.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

467
pep-0236/index.html Normal file
View File

@ -0,0 +1,467 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 236 Back to the __future__ | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0236/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 236 Back to the __future__ | peps.python.org'>
<meta property="og:description" content="Python Enhancement Proposals (PEPs)">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0236/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python Enhancement Proposals (PEPs)">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 236</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 236 Back to the __future__</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Tim Peters &lt;tim.peters&#32;&#97;t&#32;gmail.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">26-Feb-2001</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">26-Feb-2001</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#intent">Intent</a></li>
<li><a class="reference internal" href="#syntax">Syntax</a></li>
<li><a class="reference internal" href="#semantics">Semantics</a></li>
<li><a class="reference internal" href="#example">Example</a></li>
<li><a class="reference internal" href="#standard-module-future-py">Standard Module __future__.py</a></li>
<li><a class="reference internal" href="#resolved-problem-runtime-compilation">Resolved Problem: Runtime Compilation</a></li>
<li><a class="reference internal" href="#resolved-problem-native-interactive-shells">Resolved Problem: Native Interactive Shells</a></li>
<li><a class="reference internal" href="#resolved-problem-simulated-interactive-shells">Resolved Problem: Simulated Interactive Shells</a></li>
<li><a class="reference internal" href="#questions-and-answers">Questions and Answers</a><ul>
<li><a class="reference internal" href="#what-about-a-from-past-version-to-get-back-old-behavior">What about a “from __past__” version, to get back <em>old</em> behavior?</a></li>
<li><a class="reference internal" href="#what-about-incompatibilities-due-to-changes-in-the-python-virtual-machine">What about incompatibilities due to changes in the Python virtual machine?</a></li>
<li><a class="reference internal" href="#what-about-incompatibilities-due-to-changes-in-python-s-c-api">What about incompatibilities due to changes in Pythons C API?</a></li>
<li><a class="reference internal" href="#i-want-to-wrap-future-statements-in-try-except-blocks-so-i-can-use-different-code-depending-on-which-version-of-python-i-m-running-why-can-t-i">I want to wrap future_statements in try/except blocks, so I can use different code depending on which version of Python Im running. Why cant I?</a></li>
<li><a class="reference internal" href="#going-back-to-the-nested-scopes-example-what-if-release-2-2-comes-along-and-i-still-haven-t-changed-my-code-how-can-i-keep-the-2-1-behavior-then">Going back to the nested_scopes example, what if release 2.2 comes along and I still havent changed my code? How can I keep the 2.1 behavior then?</a></li>
<li><a class="reference internal" href="#overloading-import-sucks-why-not-introduce-a-new-statement-for-this">Overloading <code class="docutils literal notranslate"><span class="pre">import</span></code> sucks. Why not introduce a new statement for this?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references-and-footnotes">References and Footnotes</a></li>
</ul>
</details></section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>From time to time, Python makes an incompatible change to the advertised
semantics of core language constructs, or changes their accidental
(implementation-dependent) behavior in some way. While this is never done
capriciously, and is always done with the aim of improving the language over
the long term, over the short term its contentious and disrupting.</p>
<p><a class="pep reference internal" href="../pep-0005/" title="PEP 5 Guidelines for Language Evolution">PEP 5</a>, Guidelines for Language Evolution suggests ways to ease the pain,
and this PEP introduces some machinery in support of that.</p>
<p><a class="pep reference internal" href="../pep-0227/" title="PEP 227 Statically Nested Scopes">PEP 227</a>, Statically Nested Scopes is the first application, and will be
used as an example here.</p>
</section>
<section id="intent">
<h2><a class="toc-backref" href="#intent" role="doc-backlink">Intent</a></h2>
<p>[Note: This is policy, and so should eventually move into <a class="pep reference internal" href="../pep-0005/" title="PEP 5 Guidelines for Language Evolution">PEP 5</a>]</p>
<p>When an incompatible change to core language syntax or semantics is being
made:</p>
<ol class="arabic simple">
<li>The release C that introduces the change does not change the syntax or
semantics by default.</li>
<li>A future release R is identified in which the new syntax or semantics will
be enforced.</li>
<li>The mechanisms described in <a class="pep reference internal" href="../pep-0230/" title="PEP 230 Warning Framework">PEP 230</a>, Warning Framework are used to
generate warnings, whenever possible, about constructs or operations whose
meaning may <a class="footnote-reference brackets" href="#id3" id="id1">[1]</a> change in release R.</li>
<li>The new future_statement (see below) can be explicitly included in a module
M to request that the code in module M use the new syntax or semantics in
the current release C.</li>
</ol>
<p>So old code continues to work by default, for at least one release, although
it may start to generate new warning messages. Migration to the new syntax or
semantics can proceed during that time, using the future_statement to make
modules containing it act as if the new syntax or semantics were already being
enforced.</p>
<p>Note that there is no need to involve the future_statement machinery in new
features unless they can break existing code; fully backward- compatible
additions can and should be introduced without a corresponding
future_statement.</p>
</section>
<section id="syntax">
<h2><a class="toc-backref" href="#syntax" role="doc-backlink">Syntax</a></h2>
<p>A future_statement is simply a from/import statement using the reserved module
name <code class="docutils literal notranslate"><span class="pre">__future__</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">future_statement</span><span class="p">:</span> <span class="s2">&quot;from&quot;</span> <span class="s2">&quot;__future__&quot;</span> <span class="s2">&quot;import&quot;</span> <span class="n">feature</span> <span class="p">[</span><span class="s2">&quot;as&quot;</span> <span class="n">name</span><span class="p">]</span>
<span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="n">feature</span> <span class="p">[</span><span class="s2">&quot;as&quot;</span> <span class="n">name</span><span class="p">])</span><span class="o">*</span>
<span class="n">feature</span><span class="p">:</span> <span class="n">identifier</span>
<span class="n">name</span><span class="p">:</span> <span class="n">identifier</span>
</pre></div>
</div>
<p>In addition, all future_statements must appear near the top of the module. The
only lines that can appear before a future_statement are:</p>
<ul class="simple">
<li>The module docstring (if any).</li>
<li>Comments.</li>
<li>Blank lines.</li>
<li>Other future_statements.</li>
</ul>
<p>Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="sd">&quot;&quot;&quot;This is a module docstring.&quot;&quot;&quot;</span>
<span class="c1"># This is a comment, preceded by a blank line and followed by</span>
<span class="c1"># a future_statement.</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">nested_scopes</span>
<span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">sin</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">alabaster_weenoblobs</span> <span class="c1"># compile-time error!</span>
<span class="c1"># That was an error because preceded by a non-future_statement.</span>
</pre></div>
</div>
</section>
<section id="semantics">
<h2><a class="toc-backref" href="#semantics" role="doc-backlink">Semantics</a></h2>
<p>A future_statement is recognized and treated specially at compile time:
changes to the semantics of core constructs are often implemented by
generating different code. It may even be the case that a new feature
introduces new incompatible syntax (such as a new reserved word), in which
case the compiler may need to parse the module differently. Such decisions
cannot be pushed off until runtime.</p>
<p>For any given release, the compiler knows which feature names have been
defined, and raises a compile-time error if a future_statement contains a
feature not known to it <a class="footnote-reference brackets" href="#id4" id="id2">[2]</a>.</p>
<p>The direct runtime semantics are the same as for any <code class="docutils literal notranslate"><span class="pre">import</span></code> statement:
there is a standard module <code class="docutils literal notranslate"><span class="pre">__future__.py</span></code>, described later, and it will be
imported in the usual way at the time the future_statement is executed.</p>
<p>The <em>interesting</em> runtime semantics depend on the specific feature(s)
“imported” by the future_statement(s) appearing in the module.</p>
<p>Note that there is nothing special about the statement:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">__future__</span> <span class="p">[</span><span class="k">as</span> <span class="n">name</span><span class="p">]</span>
</pre></div>
</div>
<p>That is not a future_statement; its an ordinary import statement, with no
special semantics or syntax restrictions.</p>
</section>
<section id="example">
<h2><a class="toc-backref" href="#example" role="doc-backlink">Example</a></h2>
<p>Consider this code, in file scope.py:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="mi">42</span>
<span class="k">def</span> <span class="nf">f</span><span class="p">():</span>
<span class="n">x</span> <span class="o">=</span> <span class="mi">666</span>
<span class="k">def</span> <span class="nf">g</span><span class="p">():</span>
<span class="nb">print</span> <span class="s2">&quot;x is&quot;</span><span class="p">,</span> <span class="n">x</span>
<span class="n">g</span><span class="p">()</span>
<span class="n">f</span><span class="p">()</span>
</pre></div>
</div>
<p>Under 2.0, it prints:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="ow">is</span> <span class="mi">42</span>
</pre></div>
</div>
<p>Nested scopes (<a class="pep reference internal" href="../pep-0227/" title="PEP 227 Statically Nested Scopes">PEP 227</a>) are being introduced in 2.1. But under 2.1, it still
prints:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="ow">is</span> <span class="mi">42</span>
</pre></div>
</div>
<p>and also generates a warning.</p>
<p>In 2.2, and also in 2.1 <em>if</em> <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">nested_scopes</span></code> is
included at the top of <code class="docutils literal notranslate"><span class="pre">scope.py</span></code>, it prints:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="ow">is</span> <span class="mi">666</span>
</pre></div>
</div>
</section>
<section id="standard-module-future-py">
<h2><a class="toc-backref" href="#standard-module-future-py" role="doc-backlink">Standard Module __future__.py</a></h2>
<p><code class="docutils literal notranslate"><span class="pre">Lib/__future__.py</span></code> is a real module, and serves three purposes:</p>
<ol class="arabic simple">
<li>To avoid confusing existing tools that analyze import statements and expect
to find the modules theyre importing.</li>
<li>To ensure that future_statements run under releases prior to 2.1 at least
yield runtime exceptions (the import of <code class="docutils literal notranslate"><span class="pre">__future__</span></code> will fail, because
there was no module of that name prior to 2.1).</li>
<li>To document when incompatible changes were introduced, and when they will
be or were made mandatory. This is a form of executable documentation,
and can be inspected programmatically via importing <code class="docutils literal notranslate"><span class="pre">__future__</span></code> and
examining its contents.</li>
</ol>
<p>Each statement in <code class="docutils literal notranslate"><span class="pre">__future__.py</span></code> is of the form:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">FeatureName</span> <span class="o">=</span> <span class="s2">&quot;_Feature(&quot;</span> <span class="n">OptionalRelease</span> <span class="s2">&quot;,&quot;</span> <span class="n">MandatoryRelease</span> <span class="s2">&quot;)&quot;</span>
</pre></div>
</div>
<p>where, normally, <em>OptionalRelease</em> &lt; <em>MandatoryRelease</em>, and both are
5-tuples of the same form as <code class="docutils literal notranslate"><span class="pre">sys.version_info</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">PY_MAJOR_VERSION</span><span class="p">,</span> <span class="c1"># the 2 in 2.1.0a3; an int</span>
<span class="n">PY_MINOR_VERSION</span><span class="p">,</span> <span class="c1"># the 1; an int</span>
<span class="n">PY_MICRO_VERSION</span><span class="p">,</span> <span class="c1"># the 0; an int</span>
<span class="n">PY_RELEASE_LEVEL</span><span class="p">,</span> <span class="c1"># &quot;alpha&quot;, &quot;beta&quot;, &quot;candidate&quot; or &quot;final&quot;; string</span>
<span class="n">PY_RELEASE_SERIAL</span> <span class="c1"># the 3; an int )</span>
</pre></div>
</div>
<p><em>OptionalRelease</em> records the first release in which:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">FeatureName</span>
</pre></div>
</div>
<p>was accepted.</p>
<p>In the case of <em>MandatoryReleases</em> that have not yet occurred,
<em>MandatoryRelease</em> predicts the release in which the feature will become part
of the language.</p>
<p>Else <em>MandatoryRelease</em> records when the feature became part of the language;
in releases at or after that, modules no longer need:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">FeatureName</span>
</pre></div>
</div>
<p>to use the feature in question, but may continue to use such imports.</p>
<p><em>MandatoryRelease</em> may also be <code class="docutils literal notranslate"><span class="pre">None</span></code>, meaning that a planned feature got
dropped.</p>
<p>Instances of <code class="docutils literal notranslate"><span class="pre">class</span> <span class="pre">_Feature</span></code> have two corresponding methods,
<code class="docutils literal notranslate"><span class="pre">.getOptionalRelease()</span></code> and <code class="docutils literal notranslate"><span class="pre">.getMandatoryRelease()</span></code>.</p>
<p>No feature line will ever be deleted from <code class="docutils literal notranslate"><span class="pre">__future__.py</span></code>.</p>
<p>Example line:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">nested_scopes</span> <span class="o">=</span> <span class="n">_Feature</span><span class="p">((</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&quot;beta&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&quot;final&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
</pre></div>
</div>
<p>This means that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">nested_scopes</span>
</pre></div>
</div>
<p>will work in all releases at or after 2.1b1, and that nested_scopes are
intended to be enforced starting in release 2.2.</p>
</section>
<section id="resolved-problem-runtime-compilation">
<h2><a class="toc-backref" href="#resolved-problem-runtime-compilation" role="doc-backlink">Resolved Problem: Runtime Compilation</a></h2>
<p>Several Python features can compile code during a modules runtime:</p>
<ol class="arabic simple">
<li>The <code class="docutils literal notranslate"><span class="pre">exec</span></code> statement.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">execfile()</span></code> function.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">compile()</span></code> function.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">eval()</span></code> function.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">input()</span></code> function.</li>
</ol>
<p>Since a module M containing a future_statement naming feature F explicitly
requests that the current release act like a future release with respect to F,
any code compiled dynamically from text passed to one of these from within M
should probably also use the new syntax or semantics associated with F. The
2.1 release does behave this way.</p>
<p>This isnt always desired, though. For example, <code class="docutils literal notranslate"><span class="pre">doctest.testmod(M)</span></code>
compiles examples taken from strings in M, and those examples should use Ms
choices, not necessarily the doctest modules choices. In the 2.1 release,
this isnt possible, and no scheme has yet been suggested for working around
this. NOTE: <a class="pep reference internal" href="../pep-0264/" title="PEP 264 Future statements in simulated shells">PEP 264</a> later addressed this in a flexible way, by adding
optional arguments to <code class="docutils literal notranslate"><span class="pre">compile()</span></code>.</p>
<p>In any case, a future_statement appearing “near the top” (see Syntax above) of
text compiled dynamically by an <code class="docutils literal notranslate"><span class="pre">exec</span></code>, <code class="docutils literal notranslate"><span class="pre">execfile()</span></code> or <code class="docutils literal notranslate"><span class="pre">compile()</span></code>
applies to the code block generated, but has no further effect on the module
that executes such an <code class="docutils literal notranslate"><span class="pre">exec</span></code>, <code class="docutils literal notranslate"><span class="pre">execfile()</span></code> or <code class="docutils literal notranslate"><span class="pre">compile()</span></code>. This cant
be used to affect <code class="docutils literal notranslate"><span class="pre">eval()</span></code> or <code class="docutils literal notranslate"><span class="pre">input()</span></code>, however, because they only allow
expression input, and a future_statement is not an expression.</p>
</section>
<section id="resolved-problem-native-interactive-shells">
<h2><a class="toc-backref" href="#resolved-problem-native-interactive-shells" role="doc-backlink">Resolved Problem: Native Interactive Shells</a></h2>
<p>There are two ways to get an interactive shell:</p>
<ol class="arabic simple">
<li>By invoking Python from a command line without a script argument.</li>
<li>By invoking Python from a command line with the <code class="docutils literal notranslate"><span class="pre">-i</span></code> switch and with a
script argument.</li>
</ol>
<p>An interactive shell can be seen as an extreme case of runtime compilation
(see above): in effect, each statement typed at an interactive shell prompt
runs a new instance of <code class="docutils literal notranslate"><span class="pre">exec</span></code>, <code class="docutils literal notranslate"><span class="pre">compile()</span></code> or <code class="docutils literal notranslate"><span class="pre">execfile()</span></code>. A
future_statement typed at an interactive shell applies to the rest of the
shell sessions life, as if the future_statement had appeared at the top of a
module.</p>
</section>
<section id="resolved-problem-simulated-interactive-shells">
<h2><a class="toc-backref" href="#resolved-problem-simulated-interactive-shells" role="doc-backlink">Resolved Problem: Simulated Interactive Shells</a></h2>
<p>Interactive shells “built by hand” (by tools such as IDLE and the Emacs
Python-mode) should behave like native interactive shells (see above).
However, the machinery used internally by native interactive shells has not
been exposed, and there isnt a clear way for tools building their own
interactive shells to achieve the desired behavior.</p>
<p>NOTE: <a class="pep reference internal" href="../pep-0264/" title="PEP 264 Future statements in simulated shells">PEP 264</a> later addressed this, by adding intelligence to the standard
<code class="docutils literal notranslate"><span class="pre">codeop.py</span></code>. Simulated shells that dont use the standard library shell
helpers can get a similar effect by exploiting the new optional arguments to
<code class="docutils literal notranslate"><span class="pre">compile()</span></code> added by <a class="pep reference internal" href="../pep-0264/" title="PEP 264 Future statements in simulated shells">PEP 264</a>.</p>
</section>
<section id="questions-and-answers">
<h2><a class="toc-backref" href="#questions-and-answers" role="doc-backlink">Questions and Answers</a></h2>
<section id="what-about-a-from-past-version-to-get-back-old-behavior">
<h3><a class="toc-backref" href="#what-about-a-from-past-version-to-get-back-old-behavior" role="doc-backlink">What about a “from __past__” version, to get back <em>old</em> behavior?</a></h3>
<p>Outside the scope of this PEP. Seems unlikely to the author, though. Write a
PEP if you want to pursue it.</p>
</section>
<section id="what-about-incompatibilities-due-to-changes-in-the-python-virtual-machine">
<h3><a class="toc-backref" href="#what-about-incompatibilities-due-to-changes-in-the-python-virtual-machine" role="doc-backlink">What about incompatibilities due to changes in the Python virtual machine?</a></h3>
<p>Outside the scope of this PEP, although <a class="pep reference internal" href="../pep-0005/" title="PEP 5 Guidelines for Language Evolution">PEP 5</a> suggests a grace period
there too, and the future_statement may also have a role to play there.</p>
</section>
<section id="what-about-incompatibilities-due-to-changes-in-python-s-c-api">
<h3><a class="toc-backref" href="#what-about-incompatibilities-due-to-changes-in-python-s-c-api" role="doc-backlink">What about incompatibilities due to changes in Pythons C API?</a></h3>
<p>Outside the scope of this PEP.</p>
</section>
<section id="i-want-to-wrap-future-statements-in-try-except-blocks-so-i-can-use-different-code-depending-on-which-version-of-python-i-m-running-why-can-t-i">
<h3><a class="toc-backref" href="#i-want-to-wrap-future-statements-in-try-except-blocks-so-i-can-use-different-code-depending-on-which-version-of-python-i-m-running-why-can-t-i" role="doc-backlink">I want to wrap future_statements in try/except blocks, so I can use different code depending on which version of Python Im running. Why cant I?</a></h3>
<p>Sorry! <code class="docutils literal notranslate"><span class="pre">try/except</span></code> is a runtime feature; future_statements are primarily
compile-time gimmicks, and your <code class="docutils literal notranslate"><span class="pre">try/except</span></code> happens long after the compiler
is done. That is, by the time you do <code class="docutils literal notranslate"><span class="pre">try/except</span></code>, the semantics in effect
for the module are already a done deal. Since the <code class="docutils literal notranslate"><span class="pre">try/except</span></code> wouldnt
accomplish what it <em>looks</em> like it should accomplish, its simply not allowed.
We also want to keep these special statements very easy to find and to
recognize.</p>
<p>Note that you <em>can</em> import <code class="docutils literal notranslate"><span class="pre">__future__</span></code> directly, and use the information in
it, along with <code class="docutils literal notranslate"><span class="pre">sys.version_info</span></code>, to figure out where the release youre
running under stands in relation to a given features status.</p>
</section>
<section id="going-back-to-the-nested-scopes-example-what-if-release-2-2-comes-along-and-i-still-haven-t-changed-my-code-how-can-i-keep-the-2-1-behavior-then">
<h3><a class="toc-backref" href="#going-back-to-the-nested-scopes-example-what-if-release-2-2-comes-along-and-i-still-haven-t-changed-my-code-how-can-i-keep-the-2-1-behavior-then" role="doc-backlink">Going back to the nested_scopes example, what if release 2.2 comes along and I still havent changed my code? How can I keep the 2.1 behavior then?</a></h3>
<p>By continuing to use 2.1, and not moving to 2.2 until you do change your
code. The purpose of future_statement is to make life easier for people who
keep current with the latest release in a timely fashion. We dont hate you
if you dont, but your problems are much harder to solve, and somebody with
those problems will need to write a PEP addressing them. future_statement is
aimed at a different audience.</p>
</section>
<section id="overloading-import-sucks-why-not-introduce-a-new-statement-for-this">
<h3><a class="toc-backref" href="#overloading-import-sucks-why-not-introduce-a-new-statement-for-this" role="doc-backlink">Overloading <code class="docutils literal notranslate"><span class="pre">import</span></code> sucks. Why not introduce a new statement for this?</a></h3>
<p>Like maybe <code class="docutils literal notranslate"><span class="pre">lambda</span> <span class="pre">lambda</span> <span class="pre">nested_scopes</span></code>? That is, unless we introduce a
new keyword, we cant introduce an entirely new statement. But if we
introduce a new keyword, that in itself would break old code. That would be
too ironic to bear. Yes, overloading <code class="docutils literal notranslate"><span class="pre">import</span></code> does suck, but not as
energetically as the alternatives as is, future_statements are 100%
backward compatible.</p>
</section>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
<section id="references-and-footnotes">
<h2><a class="toc-backref" href="#references-and-footnotes" role="doc-backlink">References and Footnotes</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id3" role="doc-footnote">
<dt class="label" id="id3">[<a href="#id1">1</a>]</dt>
<dd>Note that this is <em>may</em> and not <em>will</em>: better safe than sorry. Of course
spurious warnings wont be generated when avoidable with reasonable cost.</aside>
<aside class="footnote brackets" id="id4" role="doc-footnote">
<dt class="label" id="id4">[<a href="#id2">2</a>]</dt>
<dd>This ensures that a future_statement run under a release prior to the
first one in which a given feature is known (but &gt;= 2.1) will raise a
compile-time error rather than silently do a wrong thing. If transported
to a release prior to 2.1, a runtime error will be raised because of the
failure to import <code class="docutils literal notranslate"><span class="pre">__future__</span></code> (no such module existed in the standard
distribution before the 2.1 release, and the double underscores make it a
reserved name).</aside>
</aside>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0236.rst">https://github.com/python/peps/blob/main/peps/pep-0236.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0236.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#intent">Intent</a></li>
<li><a class="reference internal" href="#syntax">Syntax</a></li>
<li><a class="reference internal" href="#semantics">Semantics</a></li>
<li><a class="reference internal" href="#example">Example</a></li>
<li><a class="reference internal" href="#standard-module-future-py">Standard Module __future__.py</a></li>
<li><a class="reference internal" href="#resolved-problem-runtime-compilation">Resolved Problem: Runtime Compilation</a></li>
<li><a class="reference internal" href="#resolved-problem-native-interactive-shells">Resolved Problem: Native Interactive Shells</a></li>
<li><a class="reference internal" href="#resolved-problem-simulated-interactive-shells">Resolved Problem: Simulated Interactive Shells</a></li>
<li><a class="reference internal" href="#questions-and-answers">Questions and Answers</a><ul>
<li><a class="reference internal" href="#what-about-a-from-past-version-to-get-back-old-behavior">What about a “from __past__” version, to get back <em>old</em> behavior?</a></li>
<li><a class="reference internal" href="#what-about-incompatibilities-due-to-changes-in-the-python-virtual-machine">What about incompatibilities due to changes in the Python virtual machine?</a></li>
<li><a class="reference internal" href="#what-about-incompatibilities-due-to-changes-in-python-s-c-api">What about incompatibilities due to changes in Pythons C API?</a></li>
<li><a class="reference internal" href="#i-want-to-wrap-future-statements-in-try-except-blocks-so-i-can-use-different-code-depending-on-which-version-of-python-i-m-running-why-can-t-i">I want to wrap future_statements in try/except blocks, so I can use different code depending on which version of Python Im running. Why cant I?</a></li>
<li><a class="reference internal" href="#going-back-to-the-nested-scopes-example-what-if-release-2-2-comes-along-and-i-still-haven-t-changed-my-code-how-can-i-keep-the-2-1-behavior-then">Going back to the nested_scopes example, what if release 2.2 comes along and I still havent changed my code? How can I keep the 2.1 behavior then?</a></li>
<li><a class="reference internal" href="#overloading-import-sucks-why-not-introduce-a-new-statement-for-this">Overloading <code class="docutils literal notranslate"><span class="pre">import</span></code> sucks. Why not introduce a new statement for this?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
<li><a class="reference internal" href="#references-and-footnotes">References and Footnotes</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0236.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

421
pep-0237/index.html Normal file
View File

@ -0,0 +1,421 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 237 Unifying Long Integers and Integers | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0237/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 237 Unifying Long Integers and Integers | peps.python.org'>
<meta property="og:description" content="Python currently distinguishes between two kinds of integers (ints): regular or short ints, limited by the size of a C long (typically 32 or 64 bits), and long ints, which are limited only by available memory. When operations on short ints yield result...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0237/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python currently distinguishes between two kinds of integers (ints): regular or short ints, limited by the size of a C long (typically 32 or 64 bits), and long ints, which are limited only by available memory. When operations on short ints yield result...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 237</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 237 Unifying Long Integers and Integers</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Moshe Zadka, Guido van Rossum</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">11-Mar-2001</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.2</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">16-Mar-2001, 14-Aug-2001, 23-Aug-2001</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#incompatibilities">Incompatibilities</a></li>
<li><a class="reference internal" href="#literals">Literals</a></li>
<li><a class="reference internal" href="#built-in-functions">Built-in Functions</a></li>
<li><a class="reference internal" href="#c-api">C API</a></li>
<li><a class="reference internal" href="#transition">Transition</a></li>
<li><a class="reference internal" href="#overflowwarning">OverflowWarning</a></li>
<li><a class="reference internal" href="#example">Example</a></li>
<li><a class="reference internal" href="#resolved-issues">Resolved Issues</a></li>
<li><a class="reference internal" href="#id1">Implementation</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Python currently distinguishes between two kinds of integers (ints): regular
or short ints, limited by the size of a C long (typically 32 or 64 bits), and
long ints, which are limited only by available memory. When operations on
short ints yield results that dont fit in a C long, they raise an error.
There are some other distinctions too. This PEP proposes to do away with most
of the differences in semantics, unifying the two types from the perspective
of the Python user.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>Many programs find a need to deal with larger numbers after the fact, and
changing the algorithms later is bothersome. It can hinder performance in the
normal case, when all arithmetic is performed using long ints whether or not
they are needed.</p>
<p>Having the machine word size exposed to the language hinders portability. For
examples Python source files and .pycs are not portable between 32-bit and
64-bit machines because of this.</p>
<p>There is also the general desire to hide unnecessary details from the Python
user when they are irrelevant for most applications. An example is memory
allocation, which is explicit in C but automatic in Python, giving us the
convenience of unlimited sizes on strings, lists, etc. It makes sense to
extend this convenience to numbers.</p>
<p>It will give new Python programmers (whether they are new to programming in
general or not) one less thing to learn before they can start using the
language.</p>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>Initially, two alternative implementations were proposed (one by each author):</p>
<ol class="arabic">
<li>The <code class="docutils literal notranslate"><span class="pre">PyInt</span></code> types slot for a C long will be turned into a:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">union</span> <span class="p">{</span>
<span class="n">long</span> <span class="n">i</span><span class="p">;</span>
<span class="n">struct</span> <span class="p">{</span>
<span class="n">unsigned</span> <span class="n">long</span> <span class="n">length</span><span class="p">;</span>
<span class="n">digit</span> <span class="n">digits</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="p">}</span> <span class="n">bignum</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Only the <code class="docutils literal notranslate"><span class="pre">n-1</span></code> lower bits of the <code class="docutils literal notranslate"><span class="pre">long</span></code> have any meaning; the top bit
is always set. This distinguishes the <code class="docutils literal notranslate"><span class="pre">union</span></code>. All <code class="docutils literal notranslate"><span class="pre">PyInt</span></code> functions
will check this bit before deciding which types of operations to use.</p>
</li>
<li>The existing short and long int types remain, but operations return
a long int instead of raising <code class="docutils literal notranslate"><span class="pre">OverflowError</span></code> when a result cannot be
represented as a short int. A new type, <code class="docutils literal notranslate"><span class="pre">integer</span></code>, may be introduced
that is an abstract base type of which both the <code class="docutils literal notranslate"><span class="pre">int</span></code> and <code class="docutils literal notranslate"><span class="pre">long</span></code>
implementation types are subclassed. This is useful so that programs can
check integer-ness with a single test:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">integer</span><span class="p">):</span> <span class="o">...</span>
</pre></div>
</div>
</li>
</ol>
<p>After some consideration, the second implementation plan was selected, since
it is far easier to implement, is backwards compatible at the C API level, and
in addition can be implemented partially as a transitional measure.</p>
</section>
<section id="incompatibilities">
<h2><a class="toc-backref" href="#incompatibilities" role="doc-backlink">Incompatibilities</a></h2>
<p>The following operations have (usually subtly) different semantics for short
and for long integers, and one or the other will have to be changed somehow.
This is intended to be an exhaustive list. If you know of any other operation
that differ in outcome depending on whether a short or a long int with the same
value is passed, please write the second author.</p>
<ul class="simple">
<li>Currently, all arithmetic operators on short ints except <code class="docutils literal notranslate"><span class="pre">&lt;&lt;</span></code> raise
<code class="docutils literal notranslate"><span class="pre">OverflowError</span></code> if the result cannot be represented as a short int. This
will be changed to return a long int instead. The following operators can
currently raise <code class="docutils literal notranslate"><span class="pre">OverflowError</span></code>: <code class="docutils literal notranslate"><span class="pre">x+y</span></code>, <code class="docutils literal notranslate"><span class="pre">x-y</span></code>, <code class="docutils literal notranslate"><span class="pre">x*y</span></code>, <code class="docutils literal notranslate"><span class="pre">x**y</span></code>,
<code class="docutils literal notranslate"><span class="pre">divmod(x,</span> <span class="pre">y)</span></code>, <code class="docutils literal notranslate"><span class="pre">x/y</span></code>, <code class="docutils literal notranslate"><span class="pre">x%y</span></code>, and <code class="docutils literal notranslate"><span class="pre">-x</span></code>. (The last four can only
overflow when the value <code class="docutils literal notranslate"><span class="pre">-sys.maxint-1</span></code> is involved.)</li>
<li>Currently, <code class="docutils literal notranslate"><span class="pre">x&lt;&lt;n</span></code> can lose bits for short ints. This will be changed to
return a long int containing all the shifted-out bits, if returning a short
int would lose bits (where changing sign is considered a special case of
losing bits).</li>
<li>Currently, hex and oct literals for short ints may specify negative values;
for example <code class="docutils literal notranslate"><span class="pre">0xffffffff</span> <span class="pre">==</span> <span class="pre">-1</span></code> on a 32-bit machine. This will be changed
to equal <code class="docutils literal notranslate"><span class="pre">0xffffffffL</span></code> (<code class="docutils literal notranslate"><span class="pre">2**32-1</span></code>).</li>
<li>Currently, the <code class="docutils literal notranslate"><span class="pre">%u</span></code>, <code class="docutils literal notranslate"><span class="pre">%x</span></code>, <code class="docutils literal notranslate"><span class="pre">%X</span></code> and <code class="docutils literal notranslate"><span class="pre">%o</span></code> string formatting operators
and the <code class="docutils literal notranslate"><span class="pre">hex()</span></code> and <code class="docutils literal notranslate"><span class="pre">oct()</span></code> built-in functions behave differently for
negative numbers: negative short ints are formatted as unsigned C long,
while negative long ints are formatted with a minus sign. This will be
changed to use the long int semantics in all cases (but without the trailing
<em>L</em> that currently distinguishes the output of <code class="docutils literal notranslate"><span class="pre">hex()</span></code> and <code class="docutils literal notranslate"><span class="pre">oct()</span></code> for
long ints). Note that this means that <code class="docutils literal notranslate"><span class="pre">%u</span></code> becomes an alias for <code class="docutils literal notranslate"><span class="pre">%d</span></code>.
It will eventually be removed.</li>
<li>Currently, <code class="docutils literal notranslate"><span class="pre">repr()</span></code> of a long int returns a string ending in <em>L</em> while
<code class="docutils literal notranslate"><span class="pre">repr()</span></code> of a short int doesnt. The <em>L</em> will be dropped; but not before
Python 3.0.</li>
<li>Currently, an operation with long operands will never return a short int.
This <em>may</em> change, since it allows some optimization. (No changes have been
made in this area yet, and none are planned.)</li>
<li>The expression <code class="docutils literal notranslate"><span class="pre">type(x).__name__</span></code> depends on whether <em>x</em> is a short or a
long int. Since implementation alternative 2 is chosen, this difference
will remain. (In Python 3.0, we <em>may</em> be able to deploy a trick to hide the
difference, because it <em>is</em> annoying to reveal the difference to user code,
and more so as the difference between the two types is less visible.)</li>
<li>Long and short ints are handled different by the <code class="docutils literal notranslate"><span class="pre">marshal</span></code> module, and by
the <code class="docutils literal notranslate"><span class="pre">pickle</span></code> and <code class="docutils literal notranslate"><span class="pre">cPickle</span></code> modules. This difference will remain (at
least until Python 3.0).</li>
<li>Short ints with small values (typically between -1 and 99 inclusive) are
<em>interned</em> whenever a result has such a value, an existing short int with
the same value is returned. This is not done for long ints with the same
values. This difference will remain. (Since there is no guarantee of this
interning, it is debatable whether this is a semantic difference but code
may exist that uses <code class="docutils literal notranslate"><span class="pre">is</span></code> for comparisons of short ints and happens to work
because of this interning. Such code may fail if used with long ints.)</li>
</ul>
</section>
<section id="literals">
<h2><a class="toc-backref" href="#literals" role="doc-backlink">Literals</a></h2>
<p>A trailing <em>L</em> at the end of an integer literal will stop having any
meaning, and will be eventually become illegal. The compiler will choose the
appropriate type solely based on the value. (Until Python 3.0, it will force
the literal to be a long; but literals without a trailing <em>L</em> may also be
long, if they are not representable as short ints.)</p>
</section>
<section id="built-in-functions">
<h2><a class="toc-backref" href="#built-in-functions" role="doc-backlink">Built-in Functions</a></h2>
<p>The function <code class="docutils literal notranslate"><span class="pre">int()</span></code> will return a short or a long int depending on the
argument value. In Python 3.0, the function <code class="docutils literal notranslate"><span class="pre">long()</span></code> will call the function
<code class="docutils literal notranslate"><span class="pre">int()</span></code>; before then, it will continue to force the result to be a long int,
but otherwise work the same way as <code class="docutils literal notranslate"><span class="pre">int()</span></code>. The built-in name <code class="docutils literal notranslate"><span class="pre">long</span></code> will
remain in the language to represent the long implementation type (unless it is
completely eradicated in Python 3.0), but using the <code class="docutils literal notranslate"><span class="pre">int()</span></code> function is
still recommended, since it will automatically return a long when needed.</p>
</section>
<section id="c-api">
<h2><a class="toc-backref" href="#c-api" role="doc-backlink">C API</a></h2>
<p>The C API remains unchanged; C code will still need to be aware of the
difference between short and long ints. (The Python 3.0 C API will probably
be completely incompatible.)</p>
<p>The <code class="docutils literal notranslate"><span class="pre">PyArg_Parse*()</span></code> APIs already accept long ints, as long as they are
within the range representable by C ints or longs, so that functions taking C
int or long argument wont have to worry about dealing with Python longs.</p>
</section>
<section id="transition">
<h2><a class="toc-backref" href="#transition" role="doc-backlink">Transition</a></h2>
<p>There are three major phases to the transition:</p>
<ol class="arabic simple">
<li>Short int operations that currently raise <code class="docutils literal notranslate"><span class="pre">OverflowError</span></code> return a long
int value instead. This is the only change in this phase. Literals will
still distinguish between short and long ints. The other semantic
differences listed above (including the behavior of <code class="docutils literal notranslate"><span class="pre">&lt;&lt;</span></code>) will remain.
Because this phase only changes situations that currently raise
<code class="docutils literal notranslate"><span class="pre">OverflowError</span></code>, it is assumed that this wont break existing code.
(Code that depends on this exception would have to be too convoluted to be
concerned about it.) For those concerned about extreme backwards
compatibility, a command line option (or a call to the warnings module)
will allow a warning or an error to be issued at this point, but this is
off by default.</li>
<li>The remaining semantic differences are addressed. In all cases the long
int semantics will prevail. Since this will introduce backwards
incompatibilities which will break some old code, this phase may require a
future statement and/or warnings, and a prolonged transition phase. The
trailing <em>L</em> will continue to be used for longs as input and by
<code class="docutils literal notranslate"><span class="pre">repr()</span></code>.<ol class="upperalpha simple">
<li>Warnings are enabled about operations that will change their numeric
outcome in stage 2B, in particular <code class="docutils literal notranslate"><span class="pre">hex()</span></code> and <code class="docutils literal notranslate"><span class="pre">oct()</span></code>, <code class="docutils literal notranslate"><span class="pre">%u</span></code>,
<code class="docutils literal notranslate"><span class="pre">%x</span></code>, <code class="docutils literal notranslate"><span class="pre">%X</span></code> and <code class="docutils literal notranslate"><span class="pre">%o</span></code>, <code class="docutils literal notranslate"><span class="pre">hex</span></code> and <code class="docutils literal notranslate"><span class="pre">oct</span></code> literals in the
(inclusive) range <code class="docutils literal notranslate"><span class="pre">[sys.maxint+1,</span> <span class="pre">sys.maxint*2+1]</span></code>, and left shifts
losing bits.</li>
<li>The new semantic for these operations are implemented. Operations that
give different results than before will <em>not</em> issue a warning.</li>
</ol>
</li>
<li>The trailing <em>L</em> is dropped from <code class="docutils literal notranslate"><span class="pre">repr()</span></code>, and made illegal on input.
(If possible, the <code class="docutils literal notranslate"><span class="pre">long</span></code> type completely disappears.) The trailing <em>L</em>
is also dropped from <code class="docutils literal notranslate"><span class="pre">hex()</span></code> and <code class="docutils literal notranslate"><span class="pre">oct()</span></code>.</li>
</ol>
<p>Phase 1 will be implemented in Python 2.2.</p>
<p>Phase 2 will be implemented gradually, with 2A in Python 2.3 and 2B in
Python 2.4.</p>
<p>Phase 3 will be implemented in Python 3.0 (at least two years after Python 2.4
is released).</p>
</section>
<section id="overflowwarning">
<h2><a class="toc-backref" href="#overflowwarning" role="doc-backlink">OverflowWarning</a></h2>
<p>Here are the rules that guide warnings generated in situations that currently
raise <code class="docutils literal notranslate"><span class="pre">OverflowError</span></code>. This applies to transition phase 1. Historical
note: despite that phase 1 was completed in Python 2.2, and phase 2A in Python
2.3, nobody noticed that OverflowWarning was still generated in Python 2.3.
It was finally disabled in Python 2.4. The Python builtin
<code class="docutils literal notranslate"><span class="pre">OverflowWarning</span></code>, and the corresponding C API <code class="docutils literal notranslate"><span class="pre">PyExc_OverflowWarning</span></code>,
are no longer generated or used in Python 2.4, but will remain for the
(unlikely) case of user code until Python 2.5.</p>
<ul>
<li>A new warning category is introduced, <code class="docutils literal notranslate"><span class="pre">OverflowWarning</span></code>. This is a
built-in name.</li>
<li>If an int result overflows, an <code class="docutils literal notranslate"><span class="pre">OverflowWarning</span></code> warning is issued, with a
message argument indicating the operation, e.g. “integer addition”. This
may or may not cause a warning message to be displayed on <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code>, or
may cause an exception to be raised, all under control of the <code class="docutils literal notranslate"><span class="pre">-W</span></code> command
line and the warnings module.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">OverflowWarning</span></code> warning is ignored by default.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">OverflowWarning</span></code> warning can be controlled like all warnings, via the
<code class="docutils literal notranslate"><span class="pre">-W</span></code> command line option or via the <code class="docutils literal notranslate"><span class="pre">warnings.filterwarnings()</span></code> call.
For example:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">Wdefault</span><span class="p">::</span><span class="n">OverflowWarning</span>
</pre></div>
</div>
<p>cause the <code class="docutils literal notranslate"><span class="pre">OverflowWarning</span></code> to be displayed the first time it occurs at a
particular source line, and:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">Werror</span><span class="p">::</span><span class="n">OverflowWarning</span>
</pre></div>
</div>
<p>cause the <code class="docutils literal notranslate"><span class="pre">OverflowWarning</span></code> to be turned into an exception whenever it
happens. The following code enables the warning from inside the program:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">warnings</span>
<span class="n">warnings</span><span class="o">.</span><span class="n">filterwarnings</span><span class="p">(</span><span class="s2">&quot;default&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">OverflowWarning</span><span class="p">)</span>
</pre></div>
</div>
<p>See the python <code class="docutils literal notranslate"><span class="pre">man</span></code> page for the <code class="docutils literal notranslate"><span class="pre">-W</span></code> option and the <code class="docutils literal notranslate"><span class="pre">warnings</span></code>
module documentation for <code class="docutils literal notranslate"><span class="pre">filterwarnings()</span></code>.</p>
</li>
<li>If the <code class="docutils literal notranslate"><span class="pre">OverflowWarning</span></code> warning is turned into an error,
<code class="docutils literal notranslate"><span class="pre">OverflowError</span></code> is substituted. This is needed for backwards
compatibility.</li>
<li>Unless the warning is turned into an exceptions, the result of the operation
(e.g., <code class="docutils literal notranslate"><span class="pre">x+y</span></code>) is recomputed after converting the arguments to long ints.</li>
</ul>
</section>
<section id="example">
<h2><a class="toc-backref" href="#example" role="doc-backlink">Example</a></h2>
<p>If you pass a long int to a C function or built-in operation that takes an
integer, it will be treated the same as a short int as long as the value fits
(by virtue of how <code class="docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code> is implemented). If the long value
doesnt fit, it will still raise an <code class="docutils literal notranslate"><span class="pre">OverflowError</span></code>. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">fact</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">n</span><span class="o">*</span><span class="n">fact</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">A</span> <span class="o">=</span> <span class="s2">&quot;ABCDEFGHIJKLMNOPQ&quot;</span>
<span class="n">n</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&quot;Gimme an int: &quot;</span><span class="p">)</span>
<span class="nb">print</span> <span class="n">A</span><span class="p">[</span><span class="n">fact</span><span class="p">(</span><span class="n">n</span><span class="p">)</span><span class="o">%</span><span class="mi">17</span><span class="p">]</span>
</pre></div>
</div>
<p>For <code class="docutils literal notranslate"><span class="pre">n</span> <span class="pre">&gt;=</span> <span class="pre">13</span></code>, this currently raises <code class="docutils literal notranslate"><span class="pre">OverflowError</span></code> (unless the user
enters a trailing <em>L</em> as part of their input), even though the calculated
index would always be in <code class="docutils literal notranslate"><span class="pre">range(17)</span></code>. With the new approach this code will
do the right thing: the index will be calculated as a long int, but its value
will be in range.</p>
</section>
<section id="resolved-issues">
<h2><a class="toc-backref" href="#resolved-issues" role="doc-backlink">Resolved Issues</a></h2>
<p>These issues, previously open, have been resolved.</p>
<ul>
<li><code class="docutils literal notranslate"><span class="pre">hex()</span></code> and <code class="docutils literal notranslate"><span class="pre">oct()</span></code> applied to longs will continue to produce a trailing
<em>L</em> until Python 3000. The original text above wasnt clear about this,
but since it didnt happen in Python 2.4 it was thought better to leave it
alone. BDFL pronouncement here:<p><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-June/065918.html">https://mail.python.org/pipermail/python-dev/2006-June/065918.html</a></p>
</li>
<li>What to do about <code class="docutils literal notranslate"><span class="pre">sys.maxint</span></code>? Leave it in, since it is still relevant
whenever the distinction between short and long ints is still relevant (e.g.
when inspecting the type of a value).</li>
<li>Should we remove <code class="docutils literal notranslate"><span class="pre">%u</span></code> completely? Remove it.</li>
<li>Should we warn about <code class="docutils literal notranslate"><span class="pre">&lt;&lt;</span></code> not truncating integers? Yes.</li>
<li>Should the overflow warning be on a portable maximum size? No.</li>
</ul>
</section>
<section id="id1">
<h2><a class="toc-backref" href="#id1" role="doc-backlink">Implementation</a></h2>
<p>The implementation work for the Python 2.x line is completed; phase 1 was
released with Python 2.2, phase 2A with Python 2.3, and phase 2B will be
released with Python 2.4 (and is already in CVS).</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0237.rst">https://github.com/python/peps/blob/main/peps/pep-0237.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0237.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#incompatibilities">Incompatibilities</a></li>
<li><a class="reference internal" href="#literals">Literals</a></li>
<li><a class="reference internal" href="#built-in-functions">Built-in Functions</a></li>
<li><a class="reference internal" href="#c-api">C API</a></li>
<li><a class="reference internal" href="#transition">Transition</a></li>
<li><a class="reference internal" href="#overflowwarning">OverflowWarning</a></li>
<li><a class="reference internal" href="#example">Example</a></li>
<li><a class="reference internal" href="#resolved-issues">Resolved Issues</a></li>
<li><a class="reference internal" href="#id1">Implementation</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0237.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

581
pep-0238/index.html Normal file
View File

@ -0,0 +1,581 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 238 Changing the Division Operator | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0238/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 238 Changing the Division Operator | peps.python.org'>
<meta property="og:description" content="The current division (/) operator has an ambiguous meaning for numerical arguments: it returns the floor of the mathematical result of division if the arguments are ints or longs, but it returns a reasonable approximation of the division result if the a...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0238/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="The current division (/) operator has an ambiguous meaning for numerical arguments: it returns the floor of the mathematical result of division if the arguments are ints or longs, but it returns a reasonable approximation of the division result if the a...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 238</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 238 Changing the Division Operator</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Moshe Zadka &lt;moshez&#32;&#97;t&#32;zadka.site.co.il&gt;,
Guido van Rossum &lt;guido&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">11-Mar-2001</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.2</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">16-Mar-2001, 26-Jul-2001, 27-Jul-2001</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#variations">Variations</a></li>
<li><a class="reference internal" href="#alternatives">Alternatives</a></li>
<li><a class="reference internal" href="#api-changes">API Changes</a></li>
<li><a class="reference internal" href="#command-line-option">Command Line Option</a></li>
<li><a class="reference internal" href="#semantics-of-floor-division">Semantics of Floor Division</a></li>
<li><a class="reference internal" href="#semantics-of-true-division">Semantics of True Division</a></li>
<li><a class="reference internal" href="#the-future-division-statement">The Future Division Statement</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#resolved-issues">Resolved Issues</a></li>
<li><a class="reference internal" href="#faq">FAQ</a><ul>
<li><a class="reference internal" href="#when-will-python-3-0-be-released">When will Python 3.0 be released?</a></li>
<li><a class="reference internal" href="#why-isn-t-true-division-called-float-division">Why isnt true division called float division?</a></li>
<li><a class="reference internal" href="#why-is-there-a-need-for-truediv-and-itruediv">Why is there a need for <code class="docutils literal notranslate"><span class="pre">__truediv__</span></code> and <code class="docutils literal notranslate"><span class="pre">__itruediv__</span></code>?</a></li>
<li><a class="reference internal" href="#how-do-i-write-code-that-works-under-the-classic-rules-as-well-as-under-the-new-rules-without-using-or-a-future-division-statement">How do I write code that works under the classic rules as well as under the new rules without using <code class="docutils literal notranslate"><span class="pre">//</span></code> or a future division statement?</a></li>
<li><a class="reference internal" href="#how-do-i-specify-the-division-semantics-for-input-compile-execfile-eval-and-exec">How do I specify the division semantics for <code class="docutils literal notranslate"><span class="pre">input()</span></code>, <code class="docutils literal notranslate"><span class="pre">compile()</span></code>, <code class="docutils literal notranslate"><span class="pre">execfile()</span></code>, <code class="docutils literal notranslate"><span class="pre">eval()</span></code> and <code class="docutils literal notranslate"><span class="pre">exec</span></code>?</a></li>
<li><a class="reference internal" href="#what-about-code-compiled-by-the-codeop-module">What about code compiled by the codeop module?</a></li>
<li><a class="reference internal" href="#will-there-be-conversion-tools-or-aids">Will there be conversion tools or aids?</a></li>
<li><a class="reference internal" href="#why-is-my-question-not-answered-here">Why is my question not answered here?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>The current division (<code class="docutils literal notranslate"><span class="pre">/</span></code>) operator has an ambiguous meaning for numerical
arguments: it returns the floor of the mathematical result of division if the
arguments are ints or longs, but it returns a reasonable approximation of the
division result if the arguments are floats or complex. This makes
expressions expecting float or complex results error-prone when integers are
not expected but possible as inputs.</p>
<p>We propose to fix this by introducing different operators for different
operations: <code class="docutils literal notranslate"><span class="pre">x/y</span></code> to return a reasonable approximation of the mathematical
result of the division (“true division”), <code class="docutils literal notranslate"><span class="pre">x//y</span></code> to return the floor
(“floor division”). We call the current, mixed meaning of x/y
“classic division”.</p>
<p>Because of severe backwards compatibility issues, not to mention a major
flamewar on c.l.py, we propose the following transitional measures (starting
with Python 2.2):</p>
<ul class="simple">
<li>Classic division will remain the default in the Python 2.x series; true
division will be standard in Python 3.0.</li>
<li>The <code class="docutils literal notranslate"><span class="pre">//</span></code> operator will be available to request floor division
unambiguously.</li>
<li>The future division statement, spelled <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">division</span></code>,
will change the <code class="docutils literal notranslate"><span class="pre">/</span></code> operator to mean true division throughout the module.</li>
<li>A command line option will enable run-time warnings for classic division
applied to int or long arguments; another command line option will make true
division the default.</li>
<li>The standard library will use the future division statement and the <code class="docutils literal notranslate"><span class="pre">//</span></code>
operator when appropriate, so as to completely avoid classic division.</li>
</ul>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>The classic division operator makes it hard to write numerical expressions
that are supposed to give correct results from arbitrary numerical inputs.
For all other operators, one can write down a formula such as <code class="docutils literal notranslate"><span class="pre">x*y**2</span> <span class="pre">+</span> <span class="pre">z</span></code>,
and the calculated result will be close to the mathematical result (within the
limits of numerical accuracy, of course) for any numerical input type (int,
long, float, or complex). But division poses a problem: if the expressions
for both arguments happen to have an integral type, it implements floor
division rather than true division.</p>
<p>The problem is unique to dynamically typed languages: in a statically typed
language like C, the inputs, typically function arguments, would be declared
as double or float, and when a call passes an integer argument, it is
converted to double or float at the time of the call. Python doesnt have
argument type declarations, so integer arguments can easily find their way
into an expression.</p>
<p>The problem is particularly pernicious since ints are perfect substitutes for
floats in all other circumstances: <code class="docutils literal notranslate"><span class="pre">math.sqrt(2)</span></code> returns the same value as
<code class="docutils literal notranslate"><span class="pre">math.sqrt(2.0)</span></code>, <code class="docutils literal notranslate"><span class="pre">3.14*100</span></code> and <code class="docutils literal notranslate"><span class="pre">3.14*100.0</span></code> return the same value, and
so on. Thus, the author of a numerical routine may only use floating point
numbers to test his code, and believe that it works correctly, and a user may
accidentally pass in an integer input value and get incorrect results.</p>
<p>Another way to look at this is that classic division makes it difficult to
write polymorphic functions that work well with either float or int arguments;
all other operators already do the right thing. No algorithm that works for
both ints and floats has a need for truncating division in one case and true
division in the other.</p>
<p>The correct work-around is subtle: casting an argument to float() is wrong if
it could be a complex number; adding 0.0 to an argument doesnt preserve the
sign of the argument if it was minus zero. The only solution without either
downside is multiplying an argument (typically the first) by 1.0. This leaves
the value and sign unchanged for float and complex, and turns int and long
into a float with the corresponding value.</p>
<p>It is the opinion of the authors that this is a real design bug in Python, and
that it should be fixed sooner rather than later. Assuming Python usage will
continue to grow, the cost of leaving this bug in the language will eventually
outweigh the cost of fixing old code there is an upper bound to the amount
of code to be fixed, but the amount of code that might be affected by the bug
in the future is unbounded.</p>
<p>Another reason for this change is the desire to ultimately unify Pythons
numeric model. This is the subject of <a class="pep reference internal" href="../pep-0228/" title="PEP 228 Reworking Pythons Numeric Model">PEP 228</a> (which is currently
incomplete). A unified numeric model removes most of the users need to be
aware of different numerical types. This is good for beginners, but also
takes away concerns about different numeric behavior for advanced programmers.
(Of course, it wont remove concerns about numerical stability and accuracy.)</p>
<p>In a unified numeric model, the different types (int, long, float, complex,
and possibly others, such as a new rational type) serve mostly as storage
optimizations, and to some extent to indicate orthogonal properties such as
inexactness or complexity. In a unified model, the integer 1 should be
indistinguishable from the floating point number 1.0 (except for its
inexactness), and both should behave the same in all numeric contexts.
Clearly, in a unified numeric model, if <code class="docutils literal notranslate"><span class="pre">a==b</span></code> and <code class="docutils literal notranslate"><span class="pre">c==d</span></code>, <code class="docutils literal notranslate"><span class="pre">a/c</span></code> should
equal <code class="docutils literal notranslate"><span class="pre">b/d</span></code> (taking some liberties due to rounding for inexact numbers), and
since everybody agrees that <code class="docutils literal notranslate"><span class="pre">1.0/2.0</span></code> equals 0.5, <code class="docutils literal notranslate"><span class="pre">1/2</span></code> should also equal
0.5. Likewise, since <code class="docutils literal notranslate"><span class="pre">1//2</span></code> equals zero, <code class="docutils literal notranslate"><span class="pre">1.0//2.0</span></code> should also equal
zero.</p>
</section>
<section id="variations">
<h2><a class="toc-backref" href="#variations" role="doc-backlink">Variations</a></h2>
<p>Aesthetically, <code class="docutils literal notranslate"><span class="pre">x//y</span></code> doesnt please everyone, and hence several variations
have been proposed. They are addressed here:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">div</span> <span class="pre">y</span></code>. This would introduce a new keyword. Since <code class="docutils literal notranslate"><span class="pre">div</span></code> is a
popular identifier, this would break a fair amount of existing code, unless
the new keyword was only recognized under a future division statement.
Since it is expected that the majority of code that needs to be converted is
dividing integers, this would greatly increase the need for the future
division statement. Even with a future statement, the general sentiment
against adding new keywords unless absolutely necessary argues against this.</li>
<li><code class="docutils literal notranslate"><span class="pre">div(x,</span> <span class="pre">y)</span></code>. This makes the conversion of old code much harder.
Replacing <code class="docutils literal notranslate"><span class="pre">x/y</span></code> with <code class="docutils literal notranslate"><span class="pre">x//y</span></code> or <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">div</span> <span class="pre">y</span></code> can be done with a simple
query replace; in most cases the programmer can easily verify that a
particular module only works with integers so all occurrences of <code class="docutils literal notranslate"><span class="pre">x/y</span></code> can
be replaced. (The query replace is still needed to weed out slashes
occurring in comments or string literals.) Replacing <code class="docutils literal notranslate"><span class="pre">x/y</span></code> with
<code class="docutils literal notranslate"><span class="pre">div(x,</span> <span class="pre">y)</span></code> would require a much more intelligent tool, since the extent
of the expressions to the left and right of the <code class="docutils literal notranslate"><span class="pre">/</span></code> must be analyzed
before the placement of the <code class="docutils literal notranslate"><span class="pre">div(</span></code> and <code class="docutils literal notranslate"><span class="pre">)</span></code> part can be decided.</li>
<li><code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">\</span> <span class="pre">y</span></code>. The backslash is already a token, meaning line continuation, and
in general it suggests an <em>escape</em> to Unix eyes. In addition (this due to
Terry Reedy) this would make things like <code class="docutils literal notranslate"><span class="pre">eval(&quot;x\y&quot;)</span></code> harder to get
right.</li>
</ul>
</section>
<section id="alternatives">
<h2><a class="toc-backref" href="#alternatives" role="doc-backlink">Alternatives</a></h2>
<p>In order to reduce the amount of old code that needs to be converted, several
alternative proposals have been put forth. Here is a brief discussion of each
proposal (or category of proposals). If you know of an alternative that was
discussed on c.l.py that isnt mentioned here, please mail the second author.</p>
<ul class="simple">
<li>Let <code class="docutils literal notranslate"><span class="pre">/</span></code> keep its classic semantics; introduce <code class="docutils literal notranslate"><span class="pre">//</span></code> for true division.
This still leaves a broken operator in the language, and invites to use the
broken behavior. It also shuts off the road to a unified numeric model a la
<a class="pep reference internal" href="../pep-0228/" title="PEP 228 Reworking Pythons Numeric Model">PEP 228</a>.</li>
<li>Let int division return a special “portmanteau” type that behaves as an
integer in integer context, but like a float in a float context. The
problem with this is that after a few operations, the int and the float
value could be miles apart, its unclear which value should be used in
comparisons, and of course many contexts (like conversion to string) dont
have a clear integer or float preference.</li>
<li>Use a directive to use specific division semantics in a module, rather than
a future statement. This retains classic division as a permanent wart in
the language, requiring future generations of Python programmers to be
aware of the problem and the remedies.</li>
<li>Use <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__past__</span> <span class="pre">import</span> <span class="pre">division</span></code> to use classic division semantics in a
module. This also retains the classic division as a permanent wart, or at
least for a long time (eventually the past division statement could raise an
<code class="docutils literal notranslate"><span class="pre">ImportError</span></code>).</li>
<li>Use a directive (or some other way) to specify the Python version for which
a specific piece of code was developed. This requires future Python
interpreters to be able to emulate <em>exactly</em> several previous versions of
Python, and moreover to do so for multiple versions within the same
interpreter. This is way too much work. A much simpler solution is to keep
multiple interpreters installed. Another argument against this is that the
version directive is almost always overspecified: most code written for
Python X.Y, works for Python X.(Y-1) and X.(Y+1) as well, so specifying X.Y
as a version is more constraining than it needs to be. At the same time,
theres no way to know at which future or past version the code will break.</li>
</ul>
</section>
<section id="api-changes">
<h2><a class="toc-backref" href="#api-changes" role="doc-backlink">API Changes</a></h2>
<p>During the transitional phase, we have to support <em>three</em> division operators
within the same program: classic division (for <code class="docutils literal notranslate"><span class="pre">/</span></code> in modules without a
future division statement), true division (for <code class="docutils literal notranslate"><span class="pre">/</span></code> in modules with a future
division statement), and floor division (for <code class="docutils literal notranslate"><span class="pre">//</span></code>). Each operator comes in
two flavors: regular, and as an augmented assignment operator (<code class="docutils literal notranslate"><span class="pre">/=</span></code> or
<code class="docutils literal notranslate"><span class="pre">//=</span></code>).</p>
<p>The names associated with these variations are:</p>
<ul>
<li>Overloaded operator methods:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">__div__</span><span class="p">(),</span> <span class="fm">__floordiv__</span><span class="p">(),</span> <span class="fm">__truediv__</span><span class="p">();</span>
<span class="n">__idiv__</span><span class="p">(),</span> <span class="fm">__ifloordiv__</span><span class="p">(),</span> <span class="fm">__itruediv__</span><span class="p">()</span><span class="o">.</span>
</pre></div>
</div>
</li>
<li>Abstract API C functions:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyNumber_Divide</span><span class="p">(),</span> <span class="n">PyNumber_FloorDivide</span><span class="p">(),</span>
<span class="n">PyNumber_TrueDivide</span><span class="p">();</span>
<span class="n">PyNumber_InPlaceDivide</span><span class="p">(),</span> <span class="n">PyNumber_InPlaceFloorDivide</span><span class="p">(),</span>
<span class="n">PyNumber_InPlaceTrueDivide</span><span class="p">()</span><span class="o">.</span>
</pre></div>
</div>
</li>
<li>Byte code opcodes:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">BINARY_DIVIDE</span><span class="p">,</span> <span class="n">BINARY_FLOOR_DIVIDE</span><span class="p">,</span> <span class="n">BINARY_TRUE_DIVIDE</span><span class="p">;</span>
<span class="n">INPLACE_DIVIDE</span><span class="p">,</span> <span class="n">INPLACE_FLOOR_DIVIDE</span><span class="p">,</span> <span class="n">INPLACE_TRUE_DIVIDE</span><span class="o">.</span>
</pre></div>
</div>
</li>
<li>PyNumberMethod slots:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">nb_divide</span><span class="p">,</span> <span class="n">nb_floor_divide</span><span class="p">,</span> <span class="n">nb_true_divide</span><span class="p">,</span>
<span class="n">nb_inplace_divide</span><span class="p">,</span> <span class="n">nb_inplace_floor_divide</span><span class="p">,</span>
<span class="n">nb_inplace_true_divide</span><span class="o">.</span>
</pre></div>
</div>
</li>
</ul>
<p>The added <code class="docutils literal notranslate"><span class="pre">PyNumberMethod</span></code> slots require an additional flag in <code class="docutils literal notranslate"><span class="pre">tp_flags</span></code>;
this flag will be named <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_NEWDIVIDE</span></code> and will be included in
<code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_DEFAULT</span></code>.</p>
<p>The true and floor division APIs will look for the corresponding slots and
call that; when that slot is <code class="docutils literal notranslate"><span class="pre">NULL</span></code>, they will raise an exception. There is
no fallback to the classic divide slot.</p>
<p>In Python 3.0, the classic division semantics will be removed; the classic
division APIs will become synonymous with true division.</p>
</section>
<section id="command-line-option">
<h2><a class="toc-backref" href="#command-line-option" role="doc-backlink">Command Line Option</a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">-Q</span></code> command line option takes a string argument that can take four
values: <code class="docutils literal notranslate"><span class="pre">old</span></code>, <code class="docutils literal notranslate"><span class="pre">warn</span></code>, <code class="docutils literal notranslate"><span class="pre">warnall</span></code>, or <code class="docutils literal notranslate"><span class="pre">new</span></code>. The default is <code class="docutils literal notranslate"><span class="pre">old</span></code>
in Python 2.2 but will change to <code class="docutils literal notranslate"><span class="pre">warn</span></code> in later 2.x versions. The <code class="docutils literal notranslate"><span class="pre">old</span></code>
value means the classic division operator acts as described. The <code class="docutils literal notranslate"><span class="pre">warn</span></code>
value means the classic division operator issues a warning (a
<code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code> using the standard warning framework) when applied
to ints or longs. The <code class="docutils literal notranslate"><span class="pre">warnall</span></code> value also issues warnings for classic
division when applied to floats or complex; this is for use by the
<code class="docutils literal notranslate"><span class="pre">fixdiv.py</span></code> conversion script mentioned below. The <code class="docutils literal notranslate"><span class="pre">new</span></code> value changes
the default globally so that the <code class="docutils literal notranslate"><span class="pre">/</span></code> operator is always interpreted as
true division. The <code class="docutils literal notranslate"><span class="pre">new</span></code> option is only intended for use in certain
educational environments, where true division is required, but asking the
students to include the future division statement in all their code would be a
problem.</p>
<p>This option will not be supported in Python 3.0; Python 3.0 will always
interpret <code class="docutils literal notranslate"><span class="pre">/</span></code> as true division.</p>
<p>(This option was originally proposed as <code class="docutils literal notranslate"><span class="pre">-D</span></code>, but that turned out to be an
existing option for Jython, hence the Q mnemonic for Quotient. Other names
have been proposed, like <code class="docutils literal notranslate"><span class="pre">-Qclassic</span></code>, <code class="docutils literal notranslate"><span class="pre">-Qclassic-warn</span></code>, <code class="docutils literal notranslate"><span class="pre">-Qtrue</span></code>, or
<code class="docutils literal notranslate"><span class="pre">-Qold_division</span></code> etc.; these seem more verbose to me without much advantage.
After all the term classic division is not used in the language at all (only
in the PEP), and the term true division is rarely used in the language only
in <code class="docutils literal notranslate"><span class="pre">__truediv__</span></code>.)</p>
</section>
<section id="semantics-of-floor-division">
<h2><a class="toc-backref" href="#semantics-of-floor-division" role="doc-backlink">Semantics of Floor Division</a></h2>
<p>Floor division will be implemented in all the Python numeric types, and will
have the semantics of:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">//</span> <span class="n">b</span> <span class="o">==</span> <span class="n">floor</span><span class="p">(</span><span class="n">a</span><span class="o">/</span><span class="n">b</span><span class="p">)</span>
</pre></div>
</div>
<p>except that the result type will be the common type into which <em>a</em> and <em>b</em> are
coerced before the operation.</p>
<p>Specifically, if <em>a</em> and <em>b</em> are of the same type, <code class="docutils literal notranslate"><span class="pre">a//b</span></code> will be of that
type too. If the inputs are of different types, they are first coerced to a
common type using the same rules used for all other arithmetic operators.</p>
<p>In particular, if <em>a</em> and <em>b</em> are both ints or longs, the result has the same
type and value as for classic division on these types (including the case of
mixed input types; <code class="docutils literal notranslate"><span class="pre">int//long</span></code> and <code class="docutils literal notranslate"><span class="pre">long//int</span></code> will both return a long).</p>
<p>For floating point inputs, the result is a float. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">3.5</span><span class="o">//</span><span class="mf">2.0</span> <span class="o">==</span> <span class="mf">1.0</span>
</pre></div>
</div>
<p>For complex numbers, <code class="docutils literal notranslate"><span class="pre">//</span></code> raises an exception, since <code class="docutils literal notranslate"><span class="pre">floor()</span></code> of a
complex number is not allowed.</p>
<p>For user-defined classes and extension types, all semantics are up to the
implementation of the class or type.</p>
</section>
<section id="semantics-of-true-division">
<h2><a class="toc-backref" href="#semantics-of-true-division" role="doc-backlink">Semantics of True Division</a></h2>
<p>True division for ints and longs will convert the arguments to float and then
apply a float division. That is, even <code class="docutils literal notranslate"><span class="pre">2/1</span></code> will return a <code class="docutils literal notranslate"><span class="pre">float</span> <span class="pre">(2.0)</span></code>,
not an int. For floats and complex, it will be the same as classic division.</p>
<p>The 2.2 implementation of true division acts as if the float type had
unbounded range, so that overflow doesnt occur unless the magnitude of the
mathematical <em>result</em> is too large to represent as a float. For example,
after <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">=</span> <span class="pre">1L</span> <span class="pre">&lt;&lt;</span> <span class="pre">40000</span></code>, <code class="docutils literal notranslate"><span class="pre">float(x)</span></code> raises <code class="docutils literal notranslate"><span class="pre">OverflowError</span></code> (note that
this is also new in 2.2: previously the outcome was platform-dependent, most
commonly a float infinity). But <code class="docutils literal notranslate"><span class="pre">x/x</span></code> returns 1.0 without exception,
while <code class="docutils literal notranslate"><span class="pre">x/1</span></code> raises <code class="docutils literal notranslate"><span class="pre">OverflowError</span></code>.</p>
<p>Note that for int and long arguments, true division may lose information; this
is in the nature of true division (as long as rationals are not in the
language). Algorithms that consciously use longs should consider using
<code class="docutils literal notranslate"><span class="pre">//</span></code>, as true division of longs retains no more than 53 bits of precision
(on most platforms).</p>
<p>If and when a rational type is added to Python (see <a class="pep reference internal" href="../pep-0239/" title="PEP 239 Adding a Rational Type to Python">PEP 239</a>), true
division for ints and longs should probably return a rational. This avoids
the problem with true division of ints and longs losing information. But
until then, for consistency, float is the only choice for true division.</p>
</section>
<section id="the-future-division-statement">
<h2><a class="toc-backref" href="#the-future-division-statement" role="doc-backlink">The Future Division Statement</a></h2>
<p>If <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">division</span></code> is present in a module, or if
<code class="docutils literal notranslate"><span class="pre">-Qnew</span></code> is used, the <code class="docutils literal notranslate"><span class="pre">/</span></code> and <code class="docutils literal notranslate"><span class="pre">/=</span></code> operators are translated to true
division opcodes; otherwise they are translated to classic division (until
Python 3.0 comes along, where they are always translated to true division).</p>
<p>The future division statement has no effect on the recognition or translation
of <code class="docutils literal notranslate"><span class="pre">//</span></code> and <code class="docutils literal notranslate"><span class="pre">//=</span></code>.</p>
<p>See <a class="pep reference internal" href="../pep-0236/" title="PEP 236 Back to the __future__">PEP 236</a> for the general rules for future statements.</p>
<p>(It has been proposed to use a longer phrase, like <em>true_division</em> or
<em>modern_division</em>. These dont seem to add much information.)</p>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
<p>We expect that these issues will be resolved over time, as more feedback is
received or we gather more experience with the initial implementation.</p>
<ul class="simple">
<li>It has been proposed to call <code class="docutils literal notranslate"><span class="pre">//</span></code> the quotient operator, and the <code class="docutils literal notranslate"><span class="pre">/</span></code>
operator the ratio operator. Im not sure about this for some people
quotient is just a synonym for division, and ratio suggests rational
numbers, which is wrong. I prefer the terminology to be slightly awkward
if that avoids unambiguity. Also, for some folks <em>quotient</em> suggests
truncation towards zero, not towards infinity as <em>floor division</em>
says explicitly.</li>
<li>It has been argued that a command line option to change the default is
evil. It can certainly be dangerous in the wrong hands: for example, it
would be impossible to combine a 3rd party library package that requires
<code class="docutils literal notranslate"><span class="pre">-Qnew</span></code> with another one that requires <code class="docutils literal notranslate"><span class="pre">-Qold</span></code>. But I believe that the
VPython folks need a way to enable true division by default, and other
educators might need the same. These usually have enough control over the
library packages available in their environment.</li>
<li>For classes to have to support all three of <code class="docutils literal notranslate"><span class="pre">__div__()</span></code>,
<code class="docutils literal notranslate"><span class="pre">__floordiv__()</span></code> and <code class="docutils literal notranslate"><span class="pre">__truediv__()</span></code> seems painful; and what to do in
3.0? Maybe we only need <code class="docutils literal notranslate"><span class="pre">__div__()</span></code> and <code class="docutils literal notranslate"><span class="pre">__floordiv__()</span></code>, or maybe at
least true division should try <code class="docutils literal notranslate"><span class="pre">__truediv__()</span></code> first and <code class="docutils literal notranslate"><span class="pre">__div__()</span></code>
second.</li>
</ul>
</section>
<section id="resolved-issues">
<h2><a class="toc-backref" href="#resolved-issues" role="doc-backlink">Resolved Issues</a></h2>
<ul>
<li>Issue: For very large long integers, the definition of true division as
returning a float causes problems, since the range of Python longs is much
larger than that of Python floats. This problem will disappear if and when
rational numbers are supported.<p>Resolution: For long true division, Python uses an internal float type with
native double precision but unbounded range, so that OverflowError doesnt
occur unless the quotient is too large to represent as a native double.</p>
</li>
<li>Issue: In the interim, maybe the long-to-float conversion could be made to
raise <code class="docutils literal notranslate"><span class="pre">OverflowError</span></code> if the long is out of range.<p>Resolution: This has been implemented, but, as above, the magnitude of the
inputs to long true division doesnt matter; only the magnitude of the
quotient matters.</p>
</li>
<li>Issue: Tim Peters will make sure that whenever an in-range float is
returned, decent precision is guaranteed.<p>Resolution: Provided the quotient of long true division is representable as
a float, it suffers no more than 3 rounding errors: one each for converting
the inputs to an internal float type with native double precision but
unbounded range, and one more for the division. However, note that if the
magnitude of the quotient is too <em>small</em> to represent as a native double,
0.0 is returned without exception (“silent underflow”).</p>
</li>
</ul>
</section>
<section id="faq">
<h2><a class="toc-backref" href="#faq" role="doc-backlink">FAQ</a></h2>
<section id="when-will-python-3-0-be-released">
<h3><a class="toc-backref" href="#when-will-python-3-0-be-released" role="doc-backlink">When will Python 3.0 be released?</a></h3>
<blockquote>
<div>We dont plan that long ahead, so we cant say for sure. We want to allow
at least two years for the transition. If Python 3.0 comes out sooner,
well keep the 2.x line alive for backwards compatibility until at least
two years from the release of Python 2.2. In practice, you will be able
to continue to use the Python 2.x line for several years after Python 3.0
is released, so you can take your time with the transition. Sites are
expected to have both Python 2.x and Python 3.x installed simultaneously.</div></blockquote>
</section>
<section id="why-isn-t-true-division-called-float-division">
<h3><a class="toc-backref" href="#why-isn-t-true-division-called-float-division" role="doc-backlink">Why isnt true division called float division?</a></h3>
<blockquote>
<div>Because I want to keep the door open to <em>possibly</em> introducing rationals
and making 1/2 return a rational rather than a float. See <a class="pep reference internal" href="../pep-0239/" title="PEP 239 Adding a Rational Type to Python">PEP 239</a>.</div></blockquote>
</section>
<section id="why-is-there-a-need-for-truediv-and-itruediv">
<h3><a class="toc-backref" href="#why-is-there-a-need-for-truediv-and-itruediv" role="doc-backlink">Why is there a need for <code class="docutils literal notranslate"><span class="pre">__truediv__</span></code> and <code class="docutils literal notranslate"><span class="pre">__itruediv__</span></code>?</a></h3>
<blockquote>
<div>We dont want to make user-defined classes second-class citizens.
Certainly not with the type/class unification going on.</div></blockquote>
</section>
<section id="how-do-i-write-code-that-works-under-the-classic-rules-as-well-as-under-the-new-rules-without-using-or-a-future-division-statement">
<h3><a class="toc-backref" href="#how-do-i-write-code-that-works-under-the-classic-rules-as-well-as-under-the-new-rules-without-using-or-a-future-division-statement" role="doc-backlink">How do I write code that works under the classic rules as well as under the new rules without using <code class="docutils literal notranslate"><span class="pre">//</span></code> or a future division statement?</a></h3>
<blockquote>
<div>Use <code class="docutils literal notranslate"><span class="pre">x*1.0/y</span></code> for true division, <code class="docutils literal notranslate"><span class="pre">divmod(x,</span> <span class="pre">y)</span></code> (<a class="pep reference internal" href="../pep-0228/" title="PEP 228 Reworking Pythons Numeric Model">PEP 228</a>) for int
division. Especially the latter is best hidden inside a function. You
may also write <code class="docutils literal notranslate"><span class="pre">float(x)/y</span></code> for true division if you are sure that you
dont expect complex numbers. If you know your integers are never
negative, you can use <code class="docutils literal notranslate"><span class="pre">int(x/y)</span></code> while the documentation of <code class="docutils literal notranslate"><span class="pre">int()</span></code>
says that <code class="docutils literal notranslate"><span class="pre">int()</span></code> can round or truncate depending on the C
implementation, we know of no C implementation that doesnt truncate, and
were going to change the spec for <code class="docutils literal notranslate"><span class="pre">int()</span></code> to promise truncation. Note
that classic division (and floor division) round towards negative
infinity, while <code class="docutils literal notranslate"><span class="pre">int()</span></code> rounds towards zero, giving different answers
for negative numbers.</div></blockquote>
</section>
<section id="how-do-i-specify-the-division-semantics-for-input-compile-execfile-eval-and-exec">
<h3><a class="toc-backref" href="#how-do-i-specify-the-division-semantics-for-input-compile-execfile-eval-and-exec" role="doc-backlink">How do I specify the division semantics for <code class="docutils literal notranslate"><span class="pre">input()</span></code>, <code class="docutils literal notranslate"><span class="pre">compile()</span></code>, <code class="docutils literal notranslate"><span class="pre">execfile()</span></code>, <code class="docutils literal notranslate"><span class="pre">eval()</span></code> and <code class="docutils literal notranslate"><span class="pre">exec</span></code>?</a></h3>
<blockquote>
<div>They inherit the choice from the invoking module. <a class="pep reference internal" href="../pep-0236/" title="PEP 236 Back to the __future__">PEP 236</a> now lists
this as a resolved problem, referring to <a class="pep reference internal" href="../pep-0264/" title="PEP 264 Future statements in simulated shells">PEP 264</a>.</div></blockquote>
</section>
<section id="what-about-code-compiled-by-the-codeop-module">
<h3><a class="toc-backref" href="#what-about-code-compiled-by-the-codeop-module" role="doc-backlink">What about code compiled by the codeop module?</a></h3>
<blockquote>
<div>This is dealt with properly; see <a class="pep reference internal" href="../pep-0264/" title="PEP 264 Future statements in simulated shells">PEP 264</a>.</div></blockquote>
</section>
<section id="will-there-be-conversion-tools-or-aids">
<h3><a class="toc-backref" href="#will-there-be-conversion-tools-or-aids" role="doc-backlink">Will there be conversion tools or aids?</a></h3>
<blockquote>
<div>Certainly. While these are outside the scope of the PEP, I should point
out two simple tools that will be released with Python 2.2a3:
<code class="docutils literal notranslate"><span class="pre">Tools/scripts/finddiv.py</span></code> finds division operators (slightly smarter
than <code class="docutils literal notranslate"><span class="pre">grep</span> <span class="pre">/</span></code>) and <code class="docutils literal notranslate"><span class="pre">Tools/scripts/fixdiv.py</span></code> can produce patches based
on run-time analysis.</div></blockquote>
</section>
<section id="why-is-my-question-not-answered-here">
<h3><a class="toc-backref" href="#why-is-my-question-not-answered-here" role="doc-backlink">Why is my question not answered here?</a></h3>
<blockquote>
<div>Because we werent aware of it. If its been discussed on c.l.py and you
believe the answer is of general interest, please notify the second
author. (We dont have the time or inclination to answer every question
sent in private email, hence the requirement that it be discussed on
c.l.py first.)</div></blockquote>
</section>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>Essentially everything mentioned here is implemented in CVS and will be
released with Python 2.2a3; most of it was already released with Python 2.2a2.</p>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0238.rst">https://github.com/python/peps/blob/main/peps/pep-0238.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0238.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#variations">Variations</a></li>
<li><a class="reference internal" href="#alternatives">Alternatives</a></li>
<li><a class="reference internal" href="#api-changes">API Changes</a></li>
<li><a class="reference internal" href="#command-line-option">Command Line Option</a></li>
<li><a class="reference internal" href="#semantics-of-floor-division">Semantics of Floor Division</a></li>
<li><a class="reference internal" href="#semantics-of-true-division">Semantics of True Division</a></li>
<li><a class="reference internal" href="#the-future-division-statement">The Future Division Statement</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#resolved-issues">Resolved Issues</a></li>
<li><a class="reference internal" href="#faq">FAQ</a><ul>
<li><a class="reference internal" href="#when-will-python-3-0-be-released">When will Python 3.0 be released?</a></li>
<li><a class="reference internal" href="#why-isn-t-true-division-called-float-division">Why isnt true division called float division?</a></li>
<li><a class="reference internal" href="#why-is-there-a-need-for-truediv-and-itruediv">Why is there a need for <code class="docutils literal notranslate"><span class="pre">__truediv__</span></code> and <code class="docutils literal notranslate"><span class="pre">__itruediv__</span></code>?</a></li>
<li><a class="reference internal" href="#how-do-i-write-code-that-works-under-the-classic-rules-as-well-as-under-the-new-rules-without-using-or-a-future-division-statement">How do I write code that works under the classic rules as well as under the new rules without using <code class="docutils literal notranslate"><span class="pre">//</span></code> or a future division statement?</a></li>
<li><a class="reference internal" href="#how-do-i-specify-the-division-semantics-for-input-compile-execfile-eval-and-exec">How do I specify the division semantics for <code class="docutils literal notranslate"><span class="pre">input()</span></code>, <code class="docutils literal notranslate"><span class="pre">compile()</span></code>, <code class="docutils literal notranslate"><span class="pre">execfile()</span></code>, <code class="docutils literal notranslate"><span class="pre">eval()</span></code> and <code class="docutils literal notranslate"><span class="pre">exec</span></code>?</a></li>
<li><a class="reference internal" href="#what-about-code-compiled-by-the-codeop-module">What about code compiled by the codeop module?</a></li>
<li><a class="reference internal" href="#will-there-be-conversion-tools-or-aids">Will there be conversion tools or aids?</a></li>
<li><a class="reference internal" href="#why-is-my-question-not-answered-here">Why is my question not answered here?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0238.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

249
pep-0239/index.html Normal file
View File

@ -0,0 +1,249 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 239 Adding a Rational Type to Python | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0239/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 239 Adding a Rational Type to Python | peps.python.org'>
<meta property="og:description" content="Python has no numeric type with the semantics of an unboundedly precise rational number. This proposal explains the semantics of such a type, and suggests builtin functions and literals to support such a type. This PEP suggests no literals for rationa...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0239/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python has no numeric type with the semantics of an unboundedly precise rational number. This proposal explains the semantics of such a type, and suggests builtin functions and literals to support such a type. This PEP suggests no literals for rationa...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 239</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 239 Adding a Rational Type to Python</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Christopher A. Craig &lt;python-pep&#32;&#97;t&#32;ccraig.org&gt;, Moshe Zadka &lt;moshez&#32;&#97;t&#32;zadka.site.co.il&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">11-Mar-2001</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.2</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">16-Mar-2001</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#rationaltype">RationalType</a></li>
<li><a class="reference internal" href="#the-rational-builtin">The rational() Builtin</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<div class="pep-banner sticky-banner deprecated rejected admonition warning">
<p class="admonition-title">Warning</p>
<p>This PEP has been rejected.</p>
<p class="close-button">×</p>
<p>The needs outlined in the rationale section
have been addressed to some extent by the acceptance of <a class="pep reference internal" href="../pep-0327/" title="PEP 327 Decimal Data Type">PEP 327</a>
for decimal arithmetic. Guido also noted, “Rational arithmetic
was the default exact arithmetic in ABC and it did not work out as
expected”. See the python-dev discussion on 17 June 2005 <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>.</p>
<p><em>Postscript:</em> With the acceptance of <a class="pep reference internal" href="../pep-3141/" title="PEP 3141 A Type Hierarchy for Numbers">PEP 3141</a>, “A Type Hierarchy
for Numbers”, a Rational numeric abstract base class was added
with a concrete implementation in the fractions module.</p>
<p></p>
</div>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Python has no numeric type with the semantics of an unboundedly
precise rational number. This proposal explains the semantics of
such a type, and suggests builtin functions and literals to
support such a type. This PEP suggests no literals for rational
numbers; that is left for <a class="pep reference internal" href="../pep-0240/" title="PEP 240 Adding a Rational Literal to Python">another PEP</a>.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>While sometimes slower and more memory intensive (in general,
unboundedly so) rational arithmetic captures more closely the
mathematical ideal of numbers, and tends to have behavior which is
less surprising to newbies. Though many Python implementations of
rational numbers have been written, none of these exist in the
core, or are documented in any way. This has made them much less
accessible to people who are less Python-savvy.</p>
</section>
<section id="rationaltype">
<h2><a class="toc-backref" href="#rationaltype" role="doc-backlink">RationalType</a></h2>
<p>There will be a new numeric type added called <code class="docutils literal notranslate"><span class="pre">RationalType</span></code>. Its
unary operators will do the obvious thing. Binary operators will
coerce integers and long integers to rationals, and rationals to
floats and complexes.</p>
<p>The following attributes will be supported: <code class="docutils literal notranslate"><span class="pre">.numerator</span></code> and
<code class="docutils literal notranslate"><span class="pre">.denominator</span></code>. The language definition will promise that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">r</span><span class="o">.</span><span class="n">denominator</span> <span class="o">*</span> <span class="n">r</span> <span class="o">==</span> <span class="n">r</span><span class="o">.</span><span class="n">numerator</span>
</pre></div>
</div>
<p>that the GCD of the numerator and the denominator is 1 and that
the denominator is positive.</p>
<p>The method <code class="docutils literal notranslate"><span class="pre">r.trim(max_denominator)</span></code> will return the closest
rational <code class="docutils literal notranslate"><span class="pre">s</span></code> to <code class="docutils literal notranslate"><span class="pre">r</span></code> such that <code class="docutils literal notranslate"><span class="pre">abs(s.denominator)</span> <span class="pre">&lt;=</span> <span class="pre">max_denominator</span></code>.</p>
</section>
<section id="the-rational-builtin">
<h2><a class="toc-backref" href="#the-rational-builtin" role="doc-backlink">The rational() Builtin</a></h2>
<p>This function will have the signature <code class="docutils literal notranslate"><span class="pre">rational(n,</span> <span class="pre">d=1)</span></code>. <code class="docutils literal notranslate"><span class="pre">n</span></code> and <code class="docutils literal notranslate"><span class="pre">d</span></code>
must both be integers, long integers or rationals. A guarantee is
made that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">rational</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span> <span class="o">*</span> <span class="n">d</span> <span class="o">==</span> <span class="n">n</span>
</pre></div>
</div>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
<ul>
<li>Maybe the type should be called rat instead of rational.
Somebody proposed that we have “abstract” pure mathematical
types named complex, real, rational, integer, and “concrete”
representation types with names like float, rat, long, int.</li>
<li>Should a rational number with an integer value be allowed as a
sequence index? For example, should <code class="docutils literal notranslate"><span class="pre">s[5/3</span> <span class="pre">-</span> <span class="pre">2/3]</span></code> be equivalent
to <code class="docutils literal notranslate"><span class="pre">s[1]</span></code>?</li>
<li>Should <code class="docutils literal notranslate"><span class="pre">shift</span></code> and <code class="docutils literal notranslate"><span class="pre">mask</span></code> operators be allowed for rational numbers?
For rational numbers with integer values?</li>
<li>Marcin Qrczak Kowalczyk summarized the arguments for and
against unifying ints with rationals nicely on c.l.py<p>Arguments for unifying ints with rationals:</p>
<ul class="simple">
<li>Since <code class="docutils literal notranslate"><span class="pre">2</span> <span class="pre">==</span> <span class="pre">2/1</span></code> and maybe <code class="docutils literal notranslate"><span class="pre">str(2/1)</span> <span class="pre">==</span> <span class="pre">'2'</span></code>, it reduces surprises
where objects seem equal but behave differently.</li>
<li><code class="docutils literal notranslate"><span class="pre">/</span></code> can be freely used for integer division when I <em>know</em> that
there is no remainder (if I am wrong and there is a remainder,
there will probably be some exception later).</li>
</ul>
<p>Arguments against:</p>
<ul class="simple">
<li>When I use the result of <code class="docutils literal notranslate"><span class="pre">/</span></code> as a sequence index, its usually
an error which should not be hidden by making the program
working for some data, since it will break for other data.</li>
<li>(this assumes that after unification int and rational would be
different types:) Types should rarely depend on values. Its
easier to reason when the type of a variable is known: I know
how I can use it. I can determine that something is an int and
expect that other objects used in this place will be ints too.</li>
<li>(this assumes the same type for them:) Int is a good type in
itself, not to be mixed with rationals. The fact that
something is an integer should be expressible as a statement
about its type. Many operations require ints and dont accept
rationals. Its natural to think about them as about different
types.</li>
</ul>
</li>
</ul>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd>Raymond Hettinger, Propose rejection of PEPs 239 and 240 a builtin
rational type and rational literals
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-June/054281.html">https://mail.python.org/pipermail/python-dev/2005-June/054281.html</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0239.rst">https://github.com/python/peps/blob/main/peps/pep-0239.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0239.rst">2024-04-14 20:08:31 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#rationaltype">RationalType</a></li>
<li><a class="reference internal" href="#the-rational-builtin">The rational() Builtin</a></li>
<li><a class="reference internal" href="#open-issues">Open Issues</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0239.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

212
pep-0240/index.html Normal file
View File

@ -0,0 +1,212 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 240 Adding a Rational Literal to Python | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0240/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 240 Adding a Rational Literal to Python | peps.python.org'>
<meta property="og:description" content="A different PEP suggests adding a builtin rational type to Python. This PEP suggests changing the ddd.ddd float literal to a rational in Python, and modifying non-integer division to return it.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0240/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="A different PEP suggests adding a builtin rational type to Python. This PEP suggests changing the ddd.ddd float literal to a rational in Python, and modifying non-integer division to return it.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 240</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 240 Adding a Rational Literal to Python</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Christopher A. Craig &lt;python-pep&#32;&#97;t&#32;ccraig.org&gt;, Moshe Zadka &lt;moshez&#32;&#97;t&#32;zadka.site.co.il&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">11-Mar-2001</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.2</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">16-Mar-2001</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#bdfl-pronouncement">BDFL Pronouncement</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
<li><a class="reference internal" href="#common-objections">Common Objections</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>A <a class="pep reference internal" href="../pep-0239/" title="PEP 239 Adding a Rational Type to Python">different PEP</a> suggests adding a builtin rational type to
Python. This PEP suggests changing the ddd.ddd float literal to a
rational in Python, and modifying non-integer division to return
it.</p>
</section>
<section id="bdfl-pronouncement">
<h2><a class="toc-backref" href="#bdfl-pronouncement" role="doc-backlink">BDFL Pronouncement</a></h2>
<p>This PEP is rejected. The needs outlined in the rationale section
have been addressed to some extent by the acceptance of <a class="pep reference internal" href="../pep-0327/" title="PEP 327 Decimal Data Type">PEP 327</a>
for decimal arithmetic. Guido also noted, “Rational arithmetic
was the default exact arithmetic in ABC and it did not work out as
expected”. See the python-dev discussion on 17 June 2005 <a class="footnote-reference brackets" href="#id2" id="id1">[1]</a>.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>Rational numbers are useful for exact and unsurprising arithmetic.
They give the correct results people have been taught in various
math classes. Making the “obvious” non-integer type one with more
predictable semantics will surprise new programmers less than
using floating point numbers. As quite a few posts on c.l.py and
on <a class="reference external" href="mailto:tutor&#37;&#52;&#48;python&#46;org">tutor<span>&#64;</span>python<span>&#46;</span>org</a> have shown, people often get bit by strange
semantics of floating point numbers: for example, <code class="docutils literal notranslate"><span class="pre">round(0.98,</span> <span class="pre">2)</span></code>
still gives 0.97999999999999998.</p>
</section>
<section id="proposal">
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
<p>Literals conforming to the regular expression <code class="docutils literal notranslate"><span class="pre">'\d*.\d*'</span></code> will be
rational numbers.</p>
</section>
<section id="backwards-compatibility">
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2>
<p>The only backwards compatible issue is the type of literals
mentioned above. The following migration is suggested:</p>
<ol class="arabic simple">
<li>The next Python after approval will allow
<code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">rational_literals</span></code>
to cause all such literals to be treated as rational numbers.</li>
<li>Python 3.0 will have a warning, turned on by default, about
such literals in the absence of a <code class="docutils literal notranslate"><span class="pre">__future__</span></code> statement. The
warning message will contain information about the <code class="docutils literal notranslate"><span class="pre">__future__</span></code>
statement, and indicate that to get floating point literals,
they should be suffixed with “e0”.</li>
<li>Python 3.1 will have the warning turned off by default. This
warning will stay in place for 24 months, at which time the
literals will be rationals and the warning will be removed.</li>
</ol>
</section>
<section id="common-objections">
<h2><a class="toc-backref" href="#common-objections" role="doc-backlink">Common Objections</a></h2>
<p>Rationals are slow and memory intensive!
(Relax, Im not taking floats away, Im just adding two more characters.
<code class="docutils literal notranslate"><span class="pre">1e0</span></code> will still be a float)</p>
<p>Rationals must present themselves as a decimal float or they will be
horrible for users expecting decimals (i.e. <code class="docutils literal notranslate"><span class="pre">str(.5)</span></code> should return <code class="docutils literal notranslate"><span class="pre">'.5'</span></code> and
not <code class="docutils literal notranslate"><span class="pre">'1/2'</span></code>). This means that many rationals must be truncated at some
point, which gives us a new loss of precision.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id2" role="doc-footnote">
<dt class="label" id="id2">[<a href="#id1">1</a>]</dt>
<dd>Raymond Hettinger, Propose rejection of PEPs 239 and 240 a builtin
rational type and rational literals
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2005-June/054281.html">https://mail.python.org/pipermail/python-dev/2005-June/054281.html</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0240.rst">https://github.com/python/peps/blob/main/peps/pep-0240.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0240.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#bdfl-pronouncement">BDFL Pronouncement</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
<li><a class="reference internal" href="#common-objections">Common Objections</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0240.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More