[pypy-commit] pypy.org extradoc: Rewrite a bit this section to focus on the commonly-encountered issue

arigo noreply at buildbot.pypy.org
Fri May 15 07:12:19 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: extradoc
Changeset: r604:e025a5c83f2c
Date: 2015-05-15 07:12 +0200
http://bitbucket.org/pypy/pypy.org/changeset/e025a5c83f2c/

Log:	Rewrite a bit this section to focus on the commonly-encountered
	issue of non-exhausted generators. Found out that they have a
	close() method.

diff --git a/compat.html b/compat.html
--- a/compat.html
+++ b/compat.html
@@ -106,34 +106,24 @@
 <li>Pillow (the PIL fork)</li>
 <li><a class="reference external" href="https://github.com/amauryfa/lxml/tree/cffi/">lxml</a></li>
 </ul>
-<p>Known differences that are not going to be fixed:</p>
-<ul>
-<li><p class="first">PyPy does not support refcounting semantics. The following code
-won't fill the file immediately, but only after a certain period
-of time, when the GC does a collection:</p>
+<p>The main difference that is not going to be fixed is that PyPy does
+not support refcounting semantics. The following code won't fill the
+file immediately, but only after a certain period of time, when the GC
+does a collection:</p>
 <div class="syntax python"><pre><span class="nb">open</span><span class="p">(</span><span class="s">"filename"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">"stuff"</span><span class="p">)</span><br/></pre></div>
 <p>The proper fix is</p>
 <div class="syntax python"><pre><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"filename"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span><br/><span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">"stuff"</span><span class="p">)</span><br/><span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span><br/></pre></div>
 <p>or using the <tt class="docutils literal">with</tt> keyword</p>
 <div class="syntax python"><pre><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"filename"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span><br/>    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">"stuff"</span><span class="p">)</span><br/></pre></div>
-<p>See <a class="reference external" href="http://pypy.readthedocs.org/en/latest/cpython_differences.html#differences-related-to-garbage-collection-strategies">more details here</a>.</p>
-</li>
-<li><p class="first">For the same reason, some functions and attributes of the <tt class="docutils literal">gc</tt> module
-behave in a slightly different way: for example, <tt class="docutils literal">gc.enable</tt> and
-<tt class="docutils literal">gc.disable</tt> are supported, but instead of enabling and disabling the GC,
-they just enable and disable the execution of finalizers.  Also,
-<tt class="docutils literal">gc.garbage</tt> always returns an empty list.</p>
-</li>
-<li><p class="first">You can't add a <tt class="docutils literal">__del__</tt> method to an existing class; it
-must be present in the class since the beginning, or else it
-will not be automatically called when instances are freed.</p>
-</li>
-<li><p class="first">You can't store non-string keys in type objects. Example</p>
-<div class="syntax python"><pre><span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span><br/>    <span class="nb">locals</span><span class="p">()[</span><span class="mi">42</span><span class="p">]</span> <span class="o">=</span> <span class="mi">3</span><br/></pre></div>
-<p>won't work.</p>
-</li>
-</ul>
-<p>A more complete list is available at <a class="reference external" href="http://pypy.readthedocs.org/en/latest/cpython_differences.html">our dev site</a>.</p>
+<p>Similarly, remember that you must <tt class="docutils literal">close()</tt> a non-exhausted
+generator in order to have its pending <tt class="docutils literal">finally</tt> or <tt class="docutils literal">with</tt>
+clauses executed immediately:</p>
+<div class="syntax python"><pre><span class="k">def</span> <span class="nf">mygen</span><span class="p">():</span><br/>    <span class="k">with</span> <span class="n">foo</span><span class="p">:</span><br/>        <span class="k">yield</span> <span class="mi">42</span><br/><br/><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">mygen</span><span class="p">():</span><br/>    <span class="k">if</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">42</span><span class="p">:</span><br/>        <span class="k">break</span>    <span class="c"># foo.__exit__ is not run immediately!</span><br/><br/><span class="c"># fixed version:</span><br/><span class="n">gen</span> <span class="o">=</span> <span class="n">mygen</span><span class="p">()</span><br/><span class="k">try</span><span class="p">:</span><br/>    <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">gen</span><span class="p">:</span><br/>        <span class="k">if</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">42</span><span class="p">:</span><br/>            <span class="k">break</span><br/><span class="k">finally</span><span class="p">:</span><br/>    <span class="n">gen</span><span class="o">.</span><span class="n">close</span><span class="p">()</span><br/></pre></div>
+<p>More generally, <tt class="docutils literal">__del__()</tt> methods are not executed as predictively
+as on CPython: they run “some time later” in PyPy (or not at all if
+the program finishes running in the meantime).  See <a class="reference external" href="http://pypy.readthedocs.org/en/latest/cpython_differences.html#differences-related-to-garbage-collection-strategies">more details
+here</a>.</p>
+<p>A more complete list of known differences is available at <a class="reference external" href="http://pypy.readthedocs.org/en/latest/cpython_differences.html">our dev site</a>.</p>
 </div>
 <div id="sidebar">
 </div>
diff --git a/source/compat.txt b/source/compat.txt
--- a/source/compat.txt
+++ b/source/compat.txt
@@ -58,53 +58,59 @@
 
 * `lxml`_
 
-Known differences that are not going to be fixed:
+The main difference that is not going to be fixed is that PyPy does
+not support refcounting semantics. The following code won't fill the
+file immediately, but only after a certain period of time, when the GC
+does a collection:
 
-* PyPy does not support refcounting semantics. The following code
-  won't fill the file immediately, but only after a certain period
-  of time, when the GC does a collection:
-
-  .. syntax:: python
+.. syntax:: python
 
     open("filename", "w").write("stuff")
 
-  The proper fix is
+The proper fix is
 
-  .. syntax:: python
+.. syntax:: python
 
     f = open("filename", "w")
     f.write("stuff")
     f.close()
 
-  or using the ``with`` keyword
+or using the ``with`` keyword
 
-  .. syntax:: python
+.. syntax:: python
 
     with open("filename", "w") as f:
         f.write("stuff")
 
-  See `more details here`_.
+Similarly, remember that you must ``close()`` a non-exhausted
+generator in order to have its pending ``finally`` or ``with``
+clauses executed immediately:
 
-* For the same reason, some functions and attributes of the ``gc`` module
-  behave in a slightly different way: for example, ``gc.enable`` and
-  ``gc.disable`` are supported, but instead of enabling and disabling the GC,
-  they just enable and disable the execution of finalizers.  Also,
-  ``gc.garbage`` always returns an empty list.
+.. syntax:: python
 
-* You can't add a ``__del__`` method to an existing class; it
-  must be present in the class since the beginning, or else it
-  will not be automatically called when instances are freed.
+    def mygen():
+        with foo:
+            yield 42
 
-* You can't store non-string keys in type objects. Example
+    for x in mygen():
+        if x == 42:
+            break    # foo.__exit__ is not run immediately!
 
-  .. syntax:: python
+    # fixed version:
+    gen = mygen()
+    try:
+        for x in gen:
+            if x == 42:
+                break
+    finally:
+        gen.close()
 
-    class A(object):
-        locals()[42] = 3
+More generally, ``__del__()`` methods are not executed as predictively
+as on CPython: they run "some time later" in PyPy (or not at all if
+the program finishes running in the meantime).  See `more details
+here`_.
 
-  won't work.
-
-A more complete list is available at `our dev site`_.
+A more complete list of known differences is available at `our dev site`_.
 
 .. _`CPython C API`: http://docs.python.org/c-api/
 .. _`CFFI`: http://cffi.readthedocs.org/


More information about the pypy-commit mailing list