Hello community,

here is the log from the commit of package python-async_generator for 
openSUSE:Factory checked in at 2019-03-05 12:19:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-async_generator (Old)
 and      /work/SRC/openSUSE:Factory/.python-async_generator.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-async_generator"

Tue Mar  5 12:19:19 2019 rev:4 rq:680420 version:1.10

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-async_generator/python-async_generator.changes
    2018-05-11 09:18:30.526007336 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-async_generator.new.28833/python-async_generator.changes
 2019-03-05 12:19:32.628947159 +0100
@@ -1,0 +2,8 @@
+Fri Mar  1 09:47:28 UTC 2019 - Ondřej Súkup <[email protected]>
+
+- update to 1.10
+- remove unnneded deps
+- fix licenses
+ * Add support for PEP 525-style garbage collection hooks
+
+-------------------------------------------------------------------

Old:
----
  async_generator-1.9.tar.gz

New:
----
  async_generator-1.10.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-async_generator.spec ++++++
--- /var/tmp/diff_new_pack.3IKhjT/_old  2019-03-05 12:19:33.064947026 +0100
+++ /var/tmp/diff_new_pack.3IKhjT/_new  2019-03-05 12:19:33.068947025 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-async_generator
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -12,30 +12,25 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-async_generator
-Version:        1.9
+Version:        1.10
 Release:        0
 Summary:        Async generators and context managers for Python 3.5+
-License:        MIT
+License:        MIT OR Apache-2.0
 Group:          Development/Languages/Python
-Url:            https://github.com/python-trio/async_generator
+URL:            https://github.com/python-trio/async_generator
 Source:         
https://files.pythonhosted.org/packages/source/a/async_generator/async_generator-%{version}.tar.gz
-BuildRequires:  %{python_module devel >= 3.5}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-%ifpython3
-Requires:       python3-base >= 3.5
-%endif
 BuildArch:      noarch
-
 %python_subpackages
 
 %description
@@ -53,10 +48,12 @@
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
-%python_exec setup.py test
+%python_exec -m pytest
 
 %files %{python_files}
 %doc README.rst
+%license LICENSE.MIT
+%license LICENSE.APACHE2
 %{python_sitelib}/*
 
 %changelog

++++++ async_generator-1.9.tar.gz -> async_generator-1.10.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/CONTRIBUTING.md 
new/async_generator-1.10/CONTRIBUTING.md
--- old/async_generator-1.9/CONTRIBUTING.md     1970-01-01 01:00:00.000000000 
+0100
+++ new/async_generator-1.10/CONTRIBUTING.md    2018-01-19 13:51:28.000000000 
+0100
@@ -0,0 +1,2 @@
+For the Trio contributing guide, see:
+    https://trio.readthedocs.io/en/latest/contributing.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/LICENSE 
new/async_generator-1.10/LICENSE
--- old/async_generator-1.9/LICENSE     1970-01-01 01:00:00.000000000 +0100
+++ new/async_generator-1.10/LICENSE    2018-01-19 13:51:28.000000000 +0100
@@ -0,0 +1,3 @@
+This software is made available under the terms of *either* of the
+licenses found in LICENSE.APACHE2 or LICENSE.MIT. Contributions to
+trio are made under the terms of *both* these licenses.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/LICENSE.APACHE2 
new/async_generator-1.10/LICENSE.APACHE2
--- old/async_generator-1.9/LICENSE.APACHE2     1970-01-01 01:00:00.000000000 
+0100
+++ new/async_generator-1.10/LICENSE.APACHE2    2018-01-19 13:51:28.000000000 
+0100
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/LICENSE.MIT 
new/async_generator-1.10/LICENSE.MIT
--- old/async_generator-1.9/LICENSE.MIT 1970-01-01 01:00:00.000000000 +0100
+++ new/async_generator-1.10/LICENSE.MIT        2018-01-19 13:51:28.000000000 
+0100
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/MANIFEST.in 
new/async_generator-1.10/MANIFEST.in
--- old/async_generator-1.9/MANIFEST.in 2016-07-03 12:38:08.000000000 +0200
+++ new/async_generator-1.10/MANIFEST.in        2018-08-01 05:20:18.000000000 
+0200
@@ -1,2 +1,6 @@
-include LICENSE.txt README.rst CODE_OF_CONDUCT.md
+include LICENSE LICENSE.MIT LICENSE.APACHE2
+include README.rst
+include CODE_OF_CONDUCT.md CONTRIBUTING.md
 include test-requirements.txt .coveragerc
+recursive-include docs *
+prune docs/build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/PKG-INFO 
new/async_generator-1.10/PKG-INFO
--- old/async_generator-1.9/PKG-INFO    2018-01-19 13:35:44.000000000 +0100
+++ new/async_generator-1.10/PKG-INFO   2018-08-01 05:36:14.000000000 +0200
@@ -1,12 +1,11 @@
 Metadata-Version: 1.2
 Name: async_generator
-Version: 1.9
+Version: 1.10
 Summary: Async generators and context managers for Python 3.5+
 Home-page: https://github.com/python-trio/async_generator
 Author: Nathaniel J. Smith
 Author-email: [email protected]
-License: MIT
-Description-Content-Type: UNKNOWN
+License: MIT -or- Apache License 2.0
 Description: .. image:: https://img.shields.io/badge/chat-join%20now-blue.svg
            :target: https://gitter.im/python-trio/general
            :alt: Join chatroom
@@ -15,16 +14,16 @@
            :target: 
https://async-generator.readthedocs.io/en/latest/?badge=latest
            :alt: Documentation Status
         
-        .. image:: 
https://travis-ci.org/njsmith/async_generator.svg?branch=master
-           :target: https://travis-ci.org/njsmith/async_generator
+        .. image:: 
https://travis-ci.org/python-trio/async_generator.svg?branch=master
+           :target: https://travis-ci.org/python-trio/async_generator
            :alt: Automated test status
         
         .. image:: 
https://ci.appveyor.com/api/projects/status/af4eyed8o8tc3t0r/branch/master?svg=true
            :target: https://ci.appveyor.com/project/python-trio/trio/history
            :alt: Automated test status (Windows)
         
-        .. image:: 
https://codecov.io/gh/njsmith/async_generator/branch/master/graph/badge.svg
-           :target: https://codecov.io/gh/njsmith/async_generator
+        .. image:: 
https://codecov.io/gh/python-trio/async_generator/branch/master/graph/badge.svg
+           :target: https://codecov.io/gh/python-trio/async_generator
            :alt: Test coverage
         
         The async_generator library
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/README.rst 
new/async_generator-1.10/README.rst
--- old/async_generator-1.9/README.rst  2018-01-19 11:14:22.000000000 +0100
+++ new/async_generator-1.10/README.rst 2018-04-23 10:59:12.000000000 +0200
@@ -6,16 +6,16 @@
    :target: https://async-generator.readthedocs.io/en/latest/?badge=latest
    :alt: Documentation Status
 
-.. image:: https://travis-ci.org/njsmith/async_generator.svg?branch=master
-   :target: https://travis-ci.org/njsmith/async_generator
+.. image:: https://travis-ci.org/python-trio/async_generator.svg?branch=master
+   :target: https://travis-ci.org/python-trio/async_generator
    :alt: Automated test status
 
 .. image:: 
https://ci.appveyor.com/api/projects/status/af4eyed8o8tc3t0r/branch/master?svg=true
    :target: https://ci.appveyor.com/project/python-trio/trio/history
    :alt: Automated test status (Windows)
 
-.. image:: 
https://codecov.io/gh/njsmith/async_generator/branch/master/graph/badge.svg
-   :target: https://codecov.io/gh/njsmith/async_generator
+.. image:: 
https://codecov.io/gh/python-trio/async_generator/branch/master/graph/badge.svg
+   :target: https://codecov.io/gh/python-trio/async_generator
    :alt: Test coverage
 
 The async_generator library
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/async_generator/__init__.py 
new/async_generator-1.10/async_generator/__init__.py
--- old/async_generator-1.9/async_generator/__init__.py 2018-01-19 
12:03:20.000000000 +0100
+++ new/async_generator-1.10/async_generator/__init__.py        2018-04-23 
10:59:12.000000000 +0200
@@ -5,6 +5,8 @@
     yield_from_,
     isasyncgen,
     isasyncgenfunction,
+    get_asyncgen_hooks,
+    set_asyncgen_hooks,
 )
 from ._util import aclosing, asynccontextmanager
 
@@ -16,4 +18,6 @@
     "isasyncgen",
     "isasyncgenfunction",
     "asynccontextmanager",
+    "get_asyncgen_hooks",
+    "set_asyncgen_hooks",
 ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/async_generator/_impl.py 
new/async_generator-1.10/async_generator/_impl.py
--- old/async_generator-1.9/async_generator/_impl.py    2018-01-19 
12:40:10.000000000 +0100
+++ new/async_generator-1.10/async_generator/_impl.py   2018-04-23 
10:59:12.000000000 +0200
@@ -45,7 +45,7 @@
 #     # We used to call _PyAsyncGenValueWrapperNew to create and set up new
 #     # wrapper objects, but that symbol isn't available on Windows:
 #     #
-#     #   https://github.com/njsmith/async_generator/issues/5
+#     #   https://github.com/python-trio/async_generator/issues/5
 #     #
 #     # Fortunately, the type object is available, but it means we have to do
 #     # this the hard way.
@@ -225,11 +225,76 @@
             return result
 
 
+UNSPECIFIED = object()
+try:
+    from sys import get_asyncgen_hooks, set_asyncgen_hooks
+
+except ImportError:
+    import threading
+
+    asyncgen_hooks = collections.namedtuple(
+        "asyncgen_hooks", ("firstiter", "finalizer")
+    )
+
+    class _hooks_storage(threading.local):
+        def __init__(self):
+            self.firstiter = None
+            self.finalizer = None
+
+    _hooks = _hooks_storage()
+
+    def get_asyncgen_hooks():
+        return asyncgen_hooks(
+            firstiter=_hooks.firstiter, finalizer=_hooks.finalizer
+        )
+
+    def set_asyncgen_hooks(firstiter=UNSPECIFIED, finalizer=UNSPECIFIED):
+        if firstiter is not UNSPECIFIED:
+            if firstiter is None or callable(firstiter):
+                _hooks.firstiter = firstiter
+            else:
+                raise TypeError(
+                    "callable firstiter expected, got {}".format(
+                        type(firstiter).__name__
+                    )
+                )
+
+        if finalizer is not UNSPECIFIED:
+            if finalizer is None or callable(finalizer):
+                _hooks.finalizer = finalizer
+            else:
+                raise TypeError(
+                    "callable finalizer expected, got {}".format(
+                        type(finalizer).__name__
+                    )
+                )
+
+
 class AsyncGenerator:
+    # https://bitbucket.org/pypy/pypy/issues/2786:
+    # PyPy implements 'await' in a way that requires the frame object
+    # used to execute a coroutine to keep a weakref to that coroutine.
+    # During a GC pass, weakrefs to all doomed objects are broken
+    # before any of the doomed objects' finalizers are invoked.
+    # If an AsyncGenerator is unreachable, its _coroutine probably
+    # is too, and the weakref from ag._coroutine.cr_frame to
+    # ag._coroutine will be broken before ag.__del__ can do its
+    # one-turn close attempt or can schedule a full aclose() using
+    # the registered finalization hook. It doesn't look like the
+    # underlying issue is likely to be fully fixed anytime soon,
+    # so we work around it by preventing an AsyncGenerator and
+    # its _coroutine from being considered newly unreachable at
+    # the same time if the AsyncGenerator's finalizer might want
+    # to iterate the coroutine some more.
+    _pypy_issue2786_workaround = set()
+
     def __init__(self, coroutine):
         self._coroutine = coroutine
         self._it = coroutine.__await__()
         self.ag_running = False
+        self._finalizer = None
+        self._closed = False
+        self._hooks_inited = False
 
     # On python 3.5.0 and 3.5.1, __aiter__ must be awaitable.
     # Starting in 3.5.2, it should not be awaitable, and if it is, then it
@@ -263,33 +328,49 @@
     # Core functionality
     ################################################################
 
-    # We make these async functions and use await, rather than just regular
-    # functions that pass back awaitables, in order to get more useful
-    # tracebacks when debugging.
+    # These need to return awaitables, rather than being async functions,
+    # to match the native behavior where the firstiter hook is called
+    # immediately on asend()/etc, even if the coroutine that asend()
+    # produces isn't awaited for a bit.
+
+    def __anext__(self):
+        return self._do_it(self._it.__next__)
+
+    def asend(self, value):
+        return self._do_it(self._it.send, value)
+
+    def athrow(self, type, value=None, traceback=None):
+        return self._do_it(self._it.throw, type, value, traceback)
+
+    def _do_it(self, start_fn, *args):
+        if not self._hooks_inited:
+            self._hooks_inited = True
+            (firstiter, self._finalizer) = get_asyncgen_hooks()
+            if firstiter is not None:
+                firstiter(self)
+            if sys.implementation.name == "pypy":
+                self._pypy_issue2786_workaround.add(self._coroutine)
 
-    async def __anext__(self):
-        return await self._do_it(self._it.__next__)
-
-    async def asend(self, value):
-        return await self._do_it(self._it.send, value)
-
-    async def athrow(self, type, value=None, traceback=None):
-        return await self._do_it(self._it.throw, type, value, traceback)
-
-    async def _do_it(self, start_fn, *args):
         # On CPython 3.5.2 (but not 3.5.0), coroutines get cranky if you try
         # to iterate them after they're exhausted. Generators OTOH just raise
         # StopIteration. We want to convert the one into the other, so we need
         # to avoid iterating stopped coroutines.
         if getcoroutinestate(self._coroutine) is CORO_CLOSED:
             raise StopAsyncIteration()
-        if self.ag_running:
-            raise ValueError("async generator already executing")
-        try:
-            self.ag_running = True
-            return await ANextIter(self._it, start_fn, *args)
-        finally:
-            self.ag_running = False
+
+        async def step():
+            if self.ag_running:
+                raise ValueError("async generator already executing")
+            try:
+                self.ag_running = True
+                return await ANextIter(self._it, start_fn, *args)
+            except StopAsyncIteration:
+                self._pypy_issue2786_workaround.discard(self._coroutine)
+                raise
+            finally:
+                self.ag_running = False
+
+        return step()
 
     ################################################################
     # Cleanup
@@ -297,32 +378,54 @@
 
     async def aclose(self):
         state = getcoroutinestate(self._coroutine)
+        if state is CORO_CLOSED or self._closed:
+            return
+        # Make sure that even if we raise "async_generator ignored
+        # GeneratorExit", and thus fail to exhaust the coroutine,
+        # __del__ doesn't complain again.
+        self._closed = True
         if state is CORO_CREATED:
             # Make sure that aclose() on an unstarted generator returns
             # successfully and prevents future iteration.
             self._it.close()
             return
-        elif state is CORO_CLOSED:
-            return
         try:
             await self.athrow(GeneratorExit)
         except (GeneratorExit, StopAsyncIteration):
-            pass
+            self._pypy_issue2786_workaround.discard(self._coroutine)
         else:
             raise RuntimeError("async_generator ignored GeneratorExit")
 
     def __del__(self):
+        self._pypy_issue2786_workaround.discard(self._coroutine)
         if getcoroutinestate(self._coroutine) is CORO_CREATED:
             # Never started, nothing to clean up, just suppress the "coroutine
             # never awaited" message.
             self._coroutine.close()
-        if getcoroutinestate(self._coroutine) is CORO_SUSPENDED:
-            # This exception will get swallowed because this is __del__, but
-            # it's an easy way to trigger the print-to-console logic
-            raise RuntimeError(
-                "partially-exhausted async_generator {!r} garbage collected"
-                .format(self._coroutine.cr_frame.f_code.co_name)
-            )
+        if getcoroutinestate(self._coroutine
+                             ) is CORO_SUSPENDED and not self._closed:
+            if self._finalizer is not None:
+                self._finalizer(self)
+            else:
+                # Mimic the behavior of native generators on GC with no 
finalizer:
+                # throw in GeneratorExit, run for one turn, and complain if it 
didn't
+                # finish.
+                thrower = self.athrow(GeneratorExit)
+                try:
+                    thrower.send(None)
+                except (GeneratorExit, StopAsyncIteration):
+                    pass
+                except StopIteration:
+                    raise RuntimeError("async_generator ignored GeneratorExit")
+                else:
+                    raise RuntimeError(
+                        "async_generator {!r} awaited during finalization; 
install "
+                        "a finalization hook to support this, or wrap it in "
+                        "'async with aclosing(...):'"
+                        .format(self.ag_code.co_name)
+                    )
+                finally:
+                    thrower.close()
 
 
 if hasattr(collections.abc, "AsyncGenerator"):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/async_generator-1.9/async_generator/_tests/test_async_generator.py 
new/async_generator-1.10/async_generator/_tests/test_async_generator.py
--- old/async_generator-1.9/async_generator/_tests/test_async_generator.py      
2018-01-19 13:01:30.000000000 +0100
+++ new/async_generator-1.10/async_generator/_tests/test_async_generator.py     
2018-04-23 10:59:12.000000000 +0200
@@ -13,6 +13,8 @@
     yield_from_,
     isasyncgen,
     isasyncgenfunction,
+    get_asyncgen_hooks,
+    set_asyncgen_hooks,
 )
 
 
@@ -190,6 +192,22 @@
             pass  # pragma: no cover
 
 
+async def test_reentrance_forbidden_simultaneous_asends():
+    @async_generator
+    async def f():
+        await mock_sleep()
+
+    ag = f()
+    sender1 = ag.asend(None)
+    sender2 = ag.asend(None)
+    assert sender1.send(None) == "mock_sleep"
+    with pytest.raises(ValueError):
+        sender2.send(None)
+    with pytest.raises(StopAsyncIteration):
+        sender1.send(None)
+    await ag.aclose()
+
+
 # https://bugs.python.org/issue32526
 async def test_reentrance_forbidden_while_suspended_in_coroutine_runner():
     @async_generator
@@ -601,31 +619,68 @@
 ################################################################
 
 
-async def test___del__():
-    gen = async_range(10)
+async def test___del__(capfd):
+    completions = 0
+
+    @async_generator
+    async def awaits_when_unwinding():
+        await yield_(0)
+        try:
+            await yield_(1)
+        finally:
+            await mock_sleep()
+        try:
+            await yield_(2)
+        finally:
+            nonlocal completions
+            completions += 1
+
+    gen = awaits_when_unwinding()
     # Hasn't started yet, so no problem
     gen.__del__()
 
-    gen = async_range(10)
-    await collect(gen)
+    gen = awaits_when_unwinding()
+    assert await collect(gen) == [0, 1, 2]
     # Exhausted, so no problem
     gen.__del__()
 
-    gen = async_range(10)
-    await gen.aclose()
-    # Closed, so no problem
-    gen.__del__()
+    for stop_after_turn in (1, 2, 3):
+        gen = awaits_when_unwinding()
+        for turn in range(stop_after_turn):
+            assert await gen.__anext__() == turn
+        await gen.aclose()
+        # Closed, so no problem
+        gen.__del__()
 
-    gen = async_range(10)
-    await gen.__anext__()
-    await gen.aclose()
-    # Closed, so no problem
-    gen.__del__()
+    for stop_after_turn in (1, 2, 3):
+        gen = awaits_when_unwinding()
+        for turn in range(stop_after_turn):
+            assert await gen.__anext__() == turn
+
+        if stop_after_turn == 2:
+            # Stopped in the middle of a try/finally that awaits in the 
finally,
+            # so __del__ can't cleanup.
+            with pytest.raises(RuntimeError) as info:
+                gen.__del__()
+            assert "awaited during finalization; install a finalization hook" 
in str(
+                info.value
+            )
+        else:
+            # Can clean up without awaiting, so __del__ is fine
+            gen.__del__()
 
-    gen = async_range(10)
-    await gen.__anext__()
-    # Started, but not exhausted or closed -- big problem
-    with pytest.raises(RuntimeError):
+    assert completions == 3
+
+    @async_generator
+    async def yields_when_unwinding():
+        try:
+            await yield_(1)
+        finally:
+            await yield_(2)
+
+    gen = yields_when_unwinding()
+    assert await gen.__anext__() == 1
+    with pytest.raises(RuntimeError) as info:
         gen.__del__()
 
 
@@ -779,3 +834,182 @@
     for msg in recwarn:  # pragma: no cover
         print(msg)
         assert not issubclass(msg.category, RuntimeWarning)
+
+
+################################################################
+#
+# GC hooks
+#
+################################################################
+
+
[email protected]
+def local_asyncgen_hooks():
+    old_hooks = get_asyncgen_hooks()
+    yield
+    set_asyncgen_hooks(*old_hooks)
+
+
+def test_gc_hooks_interface(local_asyncgen_hooks):
+    def one(agen):  # pragma: no cover
+        pass
+
+    def two(agen):  # pragma: no cover
+        pass
+
+    set_asyncgen_hooks(None, None)
+    assert get_asyncgen_hooks() == (None, None)
+    set_asyncgen_hooks(finalizer=two)
+    assert get_asyncgen_hooks() == (None, two)
+    set_asyncgen_hooks(firstiter=one)
+    assert get_asyncgen_hooks() == (one, two)
+    set_asyncgen_hooks(finalizer=None, firstiter=two)
+    assert get_asyncgen_hooks() == (two, None)
+    set_asyncgen_hooks(None, one)
+    assert get_asyncgen_hooks() == (None, one)
+    tup = (one, two)
+    set_asyncgen_hooks(*tup)
+    assert get_asyncgen_hooks() == tup
+
+    with pytest.raises(TypeError):
+        set_asyncgen_hooks(firstiter=42)
+
+    with pytest.raises(TypeError):
+        set_asyncgen_hooks(finalizer=False)
+
+    def in_thread(results):
+        results.append(get_asyncgen_hooks())
+        set_asyncgen_hooks(two, one)
+        results.append(get_asyncgen_hooks())
+
+    from threading import Thread
+    results = []
+    thread = Thread(target=in_thread, args=(results,))
+    thread.start()
+    thread.join()
+    assert results == [(None, None), (two, one)]
+    assert get_asyncgen_hooks() == (one, two)
+
+
+async def test_gc_hooks_behavior(local_asyncgen_hooks):
+    events = []
+    to_finalize = []
+
+    def firstiter(agen):
+        events.append("firstiter {}".format(agen.ag_frame.f_locals["ident"]))
+
+    def finalizer(agen):
+        events.append("finalizer {}".format(agen.ag_frame.f_locals["ident"]))
+        to_finalize.append(agen)
+
+    @async_generator
+    async def agen(ident):
+        events.append("yield 1 {}".format(ident))
+        await yield_(1)
+        try:
+            events.append("yield 2 {}".format(ident))
+            await yield_(2)
+            events.append("after yield 2 {}".format(ident))
+        finally:
+            events.append("mock_sleep {}".format(ident))
+            await mock_sleep()
+        try:
+            events.append("yield 3 {}".format(ident))
+            await yield_(3)
+        finally:
+            events.append("unwind 3 {}".format(ident))
+        # this one is included to make sure we _don't_ execute it
+        events.append("done {}".format(ident))  # pragma: no cover
+
+    async def anext_verbosely(iter, ident):
+        events.append("before asend {}".format(ident))
+        sender = iter.asend(None)
+        events.append("before send {}".format(ident))
+        await sender
+        events.append("after asend {}".format(ident))
+
+    # Ensure that firstiter is called immediately on asend(),
+    # before the first turn of the coroutine that asend() returns,
+    # to match the behavior of native generators.
+    # Ensure that the firstiter that gets used is the one in effect
+    # at the time of that first call, rather than at the time of iteration.
+    iterA = agen("A")
+    iterB = agen("B")
+    await anext_verbosely(iterA, "A")
+    set_asyncgen_hooks(firstiter, finalizer)
+    await anext_verbosely(iterB, "B")
+    iterC = agen("C")
+    await anext_verbosely(iterC, "C")
+
+    assert events == [
+        "before asend A", "before send A", "yield 1 A", "after asend A",
+        "before asend B", "firstiter B", "before send B", "yield 1 B",
+        "after asend B", "before asend C", "firstiter C", "before send C",
+        "yield 1 C", "after asend C"
+    ]
+    del events[:]
+
+    # Ensure that firstiter is only called once, even if we create
+    # two asend() coroutines before iterating either of them.
+    iterX = agen("X")
+    sender1 = iterX.asend(None)
+    sender2 = iterX.asend(None)
+    events.append("before close")
+    sender1.close()
+    sender2.close()
+    await iterX.aclose()
+    assert events == ["firstiter X", "before close"]
+    del events[:]
+
+    from weakref import ref
+    refA, refB, refC = map(ref, (iterA, iterB, iterC))
+
+    # iterA uses the finalizer that was in effect when it started, i.e. no 
finalizer
+    await iterA.__anext__()
+    await iterA.__anext__()
+    del iterA
+    # Do multiple GC passes since we're deliberately shielding the
+    # coroutine objects from the first pass due to PyPy issue 2786.
+    for _ in range(4):
+        gc.collect()
+    assert refA() is None
+    assert events == [
+        "yield 2 A", "after yield 2 A", "mock_sleep A", "yield 3 A",
+        "unwind 3 A"
+    ]
+    assert not to_finalize
+    del events[:]
+
+    # iterB and iterC do use our finalizer
+    await iterC.__anext__()
+    await iterB.__anext__()
+    await iterC.__anext__()
+    idB, idC = id(iterB), id(iterC)
+    del iterB
+    for _ in range(4):
+        gc.collect()
+    del iterC
+    for _ in range(4):
+        gc.collect()
+    assert events == [
+        "yield 2 C", "yield 2 B", "after yield 2 C", "mock_sleep C",
+        "yield 3 C", "finalizer B", "finalizer C"
+    ]
+    del events[:]
+
+    # finalizer invokes aclose() is not called again once the revived 
reference drops
+    assert list(map(id, to_finalize)) == [idB, idC]
+    events.append("before aclose B")
+    await to_finalize[0].aclose()
+    events.append("before aclose C")
+    await to_finalize[1].aclose()
+    events.append("after aclose both")
+    del to_finalize[:]
+    for _ in range(4):
+        gc.collect()
+    assert refB() is None and refC() is None
+
+    assert events == [
+        "before aclose B", "mock_sleep B", "before aclose C", "unwind 3 C",
+        "after aclose both"
+    ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/async_generator/_version.py 
new/async_generator-1.10/async_generator/_version.py
--- old/async_generator-1.9/async_generator/_version.py 2018-01-19 
13:31:58.000000000 +0100
+++ new/async_generator-1.10/async_generator/_version.py        2018-08-01 
05:35:59.000000000 +0200
@@ -1 +1 @@
-__version__ = "1.9"
+__version__ = "1.10"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/async_generator-1.9/async_generator.egg-info/PKG-INFO 
new/async_generator-1.10/async_generator.egg-info/PKG-INFO
--- old/async_generator-1.9/async_generator.egg-info/PKG-INFO   2018-01-19 
13:35:44.000000000 +0100
+++ new/async_generator-1.10/async_generator.egg-info/PKG-INFO  2018-08-01 
05:36:14.000000000 +0200
@@ -1,12 +1,11 @@
 Metadata-Version: 1.2
 Name: async-generator
-Version: 1.9
+Version: 1.10
 Summary: Async generators and context managers for Python 3.5+
 Home-page: https://github.com/python-trio/async_generator
 Author: Nathaniel J. Smith
 Author-email: [email protected]
-License: MIT
-Description-Content-Type: UNKNOWN
+License: MIT -or- Apache License 2.0
 Description: .. image:: https://img.shields.io/badge/chat-join%20now-blue.svg
            :target: https://gitter.im/python-trio/general
            :alt: Join chatroom
@@ -15,16 +14,16 @@
            :target: 
https://async-generator.readthedocs.io/en/latest/?badge=latest
            :alt: Documentation Status
         
-        .. image:: 
https://travis-ci.org/njsmith/async_generator.svg?branch=master
-           :target: https://travis-ci.org/njsmith/async_generator
+        .. image:: 
https://travis-ci.org/python-trio/async_generator.svg?branch=master
+           :target: https://travis-ci.org/python-trio/async_generator
            :alt: Automated test status
         
         .. image:: 
https://ci.appveyor.com/api/projects/status/af4eyed8o8tc3t0r/branch/master?svg=true
            :target: https://ci.appveyor.com/project/python-trio/trio/history
            :alt: Automated test status (Windows)
         
-        .. image:: 
https://codecov.io/gh/njsmith/async_generator/branch/master/graph/badge.svg
-           :target: https://codecov.io/gh/njsmith/async_generator
+        .. image:: 
https://codecov.io/gh/python-trio/async_generator/branch/master/graph/badge.svg
+           :target: https://codecov.io/gh/python-trio/async_generator
            :alt: Test coverage
         
         The async_generator library
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/async_generator-1.9/async_generator.egg-info/SOURCES.txt 
new/async_generator-1.10/async_generator.egg-info/SOURCES.txt
--- old/async_generator-1.9/async_generator.egg-info/SOURCES.txt        
2018-01-19 13:35:44.000000000 +0100
+++ new/async_generator-1.10/async_generator.egg-info/SOURCES.txt       
2018-08-01 05:36:14.000000000 +0200
@@ -1,5 +1,9 @@
 .coveragerc
 CODE_OF_CONDUCT.md
+CONTRIBUTING.md
+LICENSE
+LICENSE.APACHE2
+LICENSE.MIT
 MANIFEST.in
 README.rst
 setup.py
@@ -15,4 +19,11 @@
 async_generator/_tests/__init__.py
 async_generator/_tests/conftest.py
 async_generator/_tests/test_async_generator.py
-async_generator/_tests/test_util.py
\ No newline at end of file
+async_generator/_tests/test_util.py
+docs/Makefile
+docs/make.bat
+docs/source/conf.py
+docs/source/history.rst
+docs/source/index.rst
+docs/source/reference.rst
+docs/source/_static/.gitkeep
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/docs/Makefile 
new/async_generator-1.10/docs/Makefile
--- old/async_generator-1.9/docs/Makefile       1970-01-01 01:00:00.000000000 
+0100
+++ new/async_generator-1.10/docs/Makefile      2018-01-19 13:51:28.000000000 
+0100
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+SPHINXPROJ    = async_generator
+SOURCEDIR     = source
+BUILDDIR      = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+       @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+       @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/docs/make.bat 
new/async_generator-1.10/docs/make.bat
--- old/async_generator-1.9/docs/make.bat       1970-01-01 01:00:00.000000000 
+0100
+++ new/async_generator-1.10/docs/make.bat      2018-01-19 13:51:28.000000000 
+0100
@@ -0,0 +1,36 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+       set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+set SPHINXPROJ=async_generator
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+       echo.
+       echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+       echo.installed, then set the SPHINXBUILD environment variable to point
+       echo.to the full path of the 'sphinx-build' executable. Alternatively 
you
+       echo.may add the Sphinx directory to PATH.
+       echo.
+       echo.If you don't have Sphinx installed, grab it from
+       echo.http://sphinx-doc.org/
+       exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+
+:end
+popd
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/docs/source/conf.py 
new/async_generator-1.10/docs/source/conf.py
--- old/async_generator-1.9/docs/source/conf.py 1970-01-01 01:00:00.000000000 
+0100
+++ new/async_generator-1.10/docs/source/conf.py        2018-01-19 
13:51:28.000000000 +0100
@@ -0,0 +1,196 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Documentation build configuration file, created by
+# sphinx-quickstart on Sat Jan 21 19:11:14 2017.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+import os
+import sys
+# So autodoc can import our package
+sys.path.insert(0, os.path.abspath('../..'))
+
+# Warn about all references to unknown targets
+nitpicky = True
+# Except for these ones, which we expect to point to unknown targets:
+nitpick_ignore = [
+    # Format is ("sphinx reference type", "string"), e.g.:
+    ("py:obj", "bytes-like"),
+]
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.autodoc',
+    'sphinx.ext.intersphinx',
+    'sphinx.ext.coverage',
+    'sphinx.ext.napoleon',
+    'sphinxcontrib_trio',
+]
+
+intersphinx_mapping = {
+    # 3.7 so that we can link to contextlib.asynccontextmanager
+    # This URL can switch back to /3 after cpython 3.7 is released
+    "python": ('https://docs.python.org/3.7', None),
+    "trio": ('https://trio.readthedocs.io/en/stable', None),
+}
+
+autodoc_member_order = "bysource"
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = []
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'async_generator'
+copyright = 'The async_generator authors'
+author = 'The async_generator authors'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+import async_generator
+version = async_generator.__version__
+# The full version, including alpha/beta/rc tags.
+release = version
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = []
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# The default language for :: blocks
+highlight_language = 'python3'
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#
+#html_theme = 'alabaster'
+
+# We have to set this ourselves, not only because it's useful for local
+# testing, but also because if we don't then RTD will throw away our
+# html_theme_options.
+import sphinx_rtd_theme
+html_theme = 'sphinx_rtd_theme'
+html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#
+html_theme_options = {
+    # default is 2
+    # show deeper nesting in the RTD theme's sidebar TOC
+    # https://stackoverflow.com/questions/27669376/
+    # I'm not 100% sure this actually does anything with our current
+    # versions/settings...
+    "navigation_depth": 4,
+    "logo_only": True,
+}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+
+# -- Options for HTMLHelp output ------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'async_generatordoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+    # The paper size ('letterpaper' or 'a4paper').
+    #
+    # 'papersize': 'letterpaper',
+
+    # The font size ('10pt', '11pt' or '12pt').
+    #
+    # 'pointsize': '10pt',
+
+    # Additional stuff for the LaTeX preamble.
+    #
+    # 'preamble': '',
+
+    # Latex figure (float) alignment
+    #
+    # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+    (master_doc, 'async_generator.tex', 'Trio Documentation',
+     author, 'manual'),
+]
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'async_generator', 'async_generator Documentation',
+     [author], 1)
+]
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+    (master_doc, 'async_generator', 'async_generator Documentation',
+     author, 'async_generator', 'A short description of the project (for 
setup.py metadata)',
+     'Miscellaneous'),
+]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/docs/source/history.rst 
new/async_generator-1.10/docs/source/history.rst
--- old/async_generator-1.9/docs/source/history.rst     1970-01-01 
01:00:00.000000000 +0100
+++ new/async_generator-1.10/docs/source/history.rst    2018-08-01 
05:29:57.000000000 +0200
@@ -0,0 +1,153 @@
+Release history
+===============
+
+.. currentmodule:: async_generator
+
+.. towncrier release notes start
+
+Async_Generator 1.10 (2018-07-31)
+---------------------------------
+
+Features
+~~~~~~~~
+
+- Add support for PEP 525-style finalization hooks via
+  ``set_asyncgen_hooks()`` and ``get_asyncgen_hooks()`` functions. On
+  Python 3.6+, these are aliases for the versions in ``sys``; on
+  Python 3.5, they're work-alike implementations. And,
+  ``@async_generator`` generators now call these hooks at the
+  appropriate times. (`#15
+  <https://github.com/python-trio/trio/issues/15>`__)
+
+Fixes
+~~~~~
+
+- Package now properly includes license files. (`#11
+  <https://github.com/python-trio/async_generator/pull/11>`__)
+
+
+1.9 (2018-01-19)
+----------------
+
+* Add :func:`asynccontextmanager`
+* When a partially-exhausted ``async_generator`` is garbage collected,
+  the warning printed now includes the generator's name to help you
+  track it down.
+* Move under the auspices of the Trio project. This includes a license
+  change from MIT → dual MIT+Apache2, and various changes to internal
+  organization to match Trio project standard.
+
+1.8 (2017-06-17)
+----------------
+
+* Implement PEP 479: if a ``StopAsyncIteration`` leaks out of an async
+  generator body, wrap it into a ``RuntimeError``.
+* If an async generator was instantiated but never iterated, then we
+  used to issue a spurious "RuntimeWarning: coroutine '...' was never
+  awaited" warning. This is now fixed.
+* Add PyPy3 to our test matrix.
+* 100% test coverage.
+
+
+1.7 (2017-05-13)
+----------------
+
+* Fix a subtle bug where if you wrapped an async generator using
+  ``functools.wraps``, then ``isasyncgenfunction`` would return True
+  for the wrapper. This isn't how ``inspect.isasyncgenfunction``
+  works, and it broke ``sphinxcontrib_trio``.
+
+
+1.6 (2017-02-17)
+----------------
+
+* Add support for async generator introspection attributes
+  ``ag_running``, ``ag_code``, ``ag_frame``.
+* Attempting to re-enter a running async_generator now raises
+  ``ValueError``, just like for native async generators.
+* 100% test coverage.
+
+
+1.5 (2017-01-15)
+----------------
+
+* Remove (temporarily?) the hacks that let ``yield_`` and
+  ``yield_from_`` work with native async generators. It turns out that
+  due to obscure linking issues this was causing the library to be
+  entirely broken on Python 3.6 on Windows (but not Linux or
+  MacOS). It's probably fixable, but needs some fiddling with ctypes
+  to get the refcounting right, and I couldn't figure it out in the
+  time I had available to spend.
+
+  So in this version, everything that worked before still works with
+  ``@async_generator``-style generators, but uniformly, on all
+  platforms, ``yield_`` and ``yield_from_`` now do *not* work inside
+  native-style async generators.
+* Now running CI testing on Windows as well as Linux.
+* 100% test coverage.
+
+
+1.4 (2016-12-05)
+----------------
+
+* Allow ``await yield_()`` as an shorthand for ``await yield_(None)``
+  (thanks to Alex Grönholm for the suggestion+patch).
+* Small cleanups to setup.py and test infrastructure.
+* 100% test coverage (now including branch coverage!)
+
+
+1.3 (2016-11-24)
+----------------
+
+* Added ``isasyncgen`` and ``isasyncgenfunction``.
+* On 3.6+, register our async generators with
+  ``collections.abc.AsyncGenerator``.
+* 100% test coverage.
+
+
+1.2 (2016-11-14)
+----------------
+
+* Rewrote ``yield from`` support; now has much more accurate handling
+  of edge cases.
+* ``yield_from_`` now works inside CPython 3.6's native async
+  generators.
+* Added ``aclosing`` context manager; it's pretty trivial, but if
+  we're going to recommend it be used everywhere then it seems polite
+  to include it.
+* 100% test coverage.
+
+
+1.1 (2016-11-06)
+----------------
+
+* Support for ``asend``\/``athrow``\/``aclose``
+* Support for ``yield from``
+* Add a ``__del__`` method that complains about improperly cleaned up
+  async generators.
+* Adapt to `the change in Python 3.5.2
+  
<https://www.python.org/dev/peps/pep-0492/#api-design-and-implementation-revisions>`_
+  where ``__aiter__`` should now be a regular method instead of an
+  async method.
+* Adapt to Python 3.5.2's pickiness about iterating over
+  already-exhausted coroutines.
+* 100% test coverage.
+
+
+1.0 (2016-07-03)
+----------------
+
+* Fixes a very nasty and hard-to-hit bug where ``await yield_(...)``
+  calls could escape out to the top-level coroutine runner and get
+  lost, if the last trap out to the coroutine runner before the
+  ``await yield_(...)`` caused an exception to be injected.
+* Infinitesimally more efficient due to re-using internal
+  ``ANextIter`` objects instead of recreating them on each call to
+  ``__anext__``.
+* 100% test coverage.
+
+
+0.0.1 (2016-05-31)
+------------------
+
+Initial release.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/docs/source/index.rst 
new/async_generator-1.10/docs/source/index.rst
--- old/async_generator-1.9/docs/source/index.rst       1970-01-01 
01:00:00.000000000 +0100
+++ new/async_generator-1.10/docs/source/index.rst      2018-01-19 
13:51:28.000000000 +0100
@@ -0,0 +1,24 @@
+.. documentation master file, created by
+   sphinx-quickstart on Sat Jan 21 19:11:14 2017.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+
+=====================================================================
+async_generator: Async generators and related tools for older Pythons
+=====================================================================
+
+.. toctree::
+   :maxdepth: 2
+
+   reference.rst
+   history.rst
+
+====================
+ Indices and tables
+====================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+* :ref:`glossary`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/docs/source/reference.rst 
new/async_generator-1.10/docs/source/reference.rst
--- old/async_generator-1.9/docs/source/reference.rst   1970-01-01 
01:00:00.000000000 +0100
+++ new/async_generator-1.10/docs/source/reference.rst  2018-04-23 
10:59:12.000000000 +0200
@@ -0,0 +1,187 @@
+API documentation
+=================
+
+Async generators
+----------------
+
+In Python 3.6+, you can write a native async generator like this::
+
+    async def load_json_lines(stream_reader):
+        async for line in stream_reader:
+            yield json.loads(line)
+
+Here's the same thing written with this library, which works on Python 3.5+::
+
+    from async_generator import async_generator, yield
+
+    @async_generator
+    async def load_json_lines(stream_reader):
+        async for line in stream_reader:
+            await yield_(json.loads(line))
+
+Basically:
+
+* decorate your function with ``@async_generator``
+* replace ``yield`` with ``await yield_()``
+* replace ``yield X`` with ``await yield_(X)``
+
+That's it!
+
+
+Yield from
+~~~~~~~~~~
+
+Native async generators don't support ``yield from``::
+
+    # Doesn't work!
+    async def wrap_load_json_lines(stream_reader):
+        # This is a SyntaxError
+        yield from load_json_lines(stream_reader)
+
+But we do::
+
+    from async_generator import async_generator, yield_from_
+
+    # This works!
+    @async_generator
+    async def wrap_load_json_lines(stream_reader):
+        await yield_from_(load_json_lines(stream_reader))
+
+You can only use ``yield_from_`` inside an ``@async_generator``
+function, BUT the thing you PASS to ``yield_from_`` can be any kind of
+async iterator, including native async generators.
+
+Our ``yield_from_`` fully supports the classic ``yield from``
+semantics, including forwarding ``asend`` and ``athrow`` calls into
+the delegated async generator, and returning values::
+
+    from async_generator import async_generator, yield_, yield_from_
+
+    @async_generator
+    async def agen1():
+        await yield_(1)
+        await yield_(2)
+        return "great!"
+
+    @async_generator
+    async def agen2():
+        value = await yield_from_(agen1())
+        assert value == "great!"
+
+
+Introspection
+~~~~~~~~~~~~~
+
+For introspection purposes, we also export the following functions:
+
+.. function:: isasyncgen(agen_obj)
+
+   Returns true if passed either an async generator object created by
+   this library, or a native Python 3.6+ async generator object.
+   Analogous to :func:`inspect.isasyncgen` in 3.6+.
+
+.. function:: isasyncgenfunction(agen_func)
+
+   Returns true if passed either an async generator function created
+   by this library, or a native Python 3.6+ async generator function.
+   Analogous to :func:`inspect.isasyncgenfunction` in 3.6+.
+
+Example::
+
+   >>> isasyncgenfunction(load_json_lines)
+   True
+   >>> gen_object = load_json_lines(asyncio_stream_reader)
+   >>> isasyncgen(gen_object)
+   True
+
+In addition, this library's async generator objects are registered
+with the ``collections.abc.AsyncGenerator`` abstract base class (if
+available)::
+
+   >>> isinstance(gen_object, collections.abc.AsyncGenerator)
+   True
+
+
+Semantics
+~~~~~~~~~
+
+This library generally tries hard to match the semantics of Python
+3.6's native async generators in every detail (`PEP 525
+<https://www.python.org/dev/peps/pep-0525/>`__), with additional
+support for ``yield from`` and for returning non-None values from
+an async generator (under the theory that these may well be added
+to native async generators one day).
+
+
+Garbage collection hooks
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+This library fully supports the native async generator
+`finalization semantics 
<https://www.python.org/dev/peps/pep-0525/#finalization>`__,
+including the per-thread ``firstiter`` and ``finalizer`` hooks.
+You can use ``async_generator.set_asyncgen_hooks()`` exactly
+like you would use ``sys.set_asyncgen_hooks()`` with native
+generators. On Python 3.6+, the former is an alias for the latter,
+so libraries that use the native mechanism should work seamlessly
+with ``@async_generator`` functions. On Python 3.5, where there is
+no ``sys.set_asyncgen_hooks()``, most libraries probably *won't* know
+about ``async_generator.set_asyncgen_hooks()``, so you'll need
+to exercise more care with explicit cleanup, or install appropriate
+hooks yourself.
+
+While finishing cleanup of an async generator is better than dropping
+it on the floor at the first ``await``, it's still not a perfect solution;
+in addition to the unpredictability of GC timing, the ``finalizer`` hook
+has no practical way to determine the context in which the generator was
+being iterated, so an exception thrown from the generator during ``aclose()``
+must either crash the program or get discarded. It's much better to close
+your generators explicitly when you're done with them, perhaps using the
+:ref:`aclosing context manager <contextmanagers>`. See `this discussion
+<https://vorpus.org/blog/some-thoughts-on-asynchronous-api-design-in-a-post-asyncawait-world/#cleanup-in-generators-and-async-generators>`__
+and `PEP 533 <https://www.python.org/dev/peps/pep-0533/>`__ for more
+details.
+
+
+.. _contextmanagers:
+
+Context managers
+----------------
+
+As discussed above, you should always explicitly call ``aclose`` on
+async generators. To make this more convenient, this library also
+includes an ``aclosing`` async context manager. It acts just like the
+``closing`` context manager included in the stdlib ``contextlib``
+module, but does ``await obj.aclose()`` instead of
+``obj.close()``. Use it like this::
+
+   from async_generator import aclosing
+
+   async with aclosing(load_json_lines(asyncio_stream_reader)) as agen:
+       async for json_obj in agen:
+           ...
+
+Or if you want to write your own async context managers, we've got you
+covered:
+
+.. function:: asynccontextmanager
+   :decorator:
+
+   This is a backport of :func:`contextlib.asynccontextmanager`, which
+   wasn't added to the standard library until Python 3.7.
+
+You can use ``@asynccontextmanager`` with either native async
+generators, or the ones from this package. If you use it with the ones
+from this package, remember that ``@asynccontextmanager`` goes *on
+top* of ``@async_generator``::
+
+   # Correct!
+   @asynccontextmanager
+   @async_generator
+   async def my_async_context_manager():
+       ...
+
+   # This won't work :-(
+   @async_generator
+   @asynccontextmanager
+   async def my_async_context_manager():
+       ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/async_generator-1.9/setup.py 
new/async_generator-1.10/setup.py
--- old/async_generator-1.9/setup.py    2018-01-19 11:33:29.000000000 +0100
+++ new/async_generator-1.10/setup.py   2018-08-01 05:20:18.000000000 +0200
@@ -13,7 +13,7 @@
     long_description=Path(__file__).with_name("README.rst").read_text('utf-8'),
     author="Nathaniel J. Smith",
     author_email="[email protected]",
-    license="MIT",
+    license="MIT -or- Apache License 2.0",
     packages=find_packages(),
     url="https://github.com/python-trio/async_generator";,
     python_requires=">=3.5",


Reply via email to