Skip to content

add a Generator ABC #68206

Closed
Closed

Description

@scoder
BPO 24018
Nosy @gvanrossum, @rhettinger, @pitrou, @scoder, @vstinner, @ambv, @vadmium, @1st1
Files
  • generator_abc.patch: implementation of a Generator ABC
  • generator_abc.patch: updated patch that improves close() implementation and test coverage
  • generator_abc.patch: updated patch: check GeneratorExit propagation
  • inspect_docs.patch: update inspect docs to state that isinstance() is better than isgenerator()
  • generator_abc.patch: updated implementation: make throw() abstract
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/rhettinger'
    closed_at = <Date 2015-05-09.05:08:15.882>
    created_at = <Date 2015-04-20.19:36:25.857>
    labels = ['type-feature', 'library']
    title = 'add a Generator ABC'
    updated_at = <Date 2015-05-09.18:38:11.022>
    user = 'https://github.com/scoder'

    bugs.python.org fields:

    activity = <Date 2015-05-09.18:38:11.022>
    actor = 'gvanrossum'
    assignee = 'rhettinger'
    closed = True
    closed_date = <Date 2015-05-09.05:08:15.882>
    closer = 'rhettinger'
    components = ['Library (Lib)']
    creation = <Date 2015-04-20.19:36:25.857>
    creator = 'scoder'
    dependencies = []
    files = ['39151', '39156', '39157', '39180', '39213']
    hgrepos = []
    issue_num = 24018
    keywords = ['patch']
    message_count = 36.0
    messages = ['241675', '241677', '241681', '241682', '241683', '241692', '241700', '241701', '241702', '241703', '241704', '241705', '241716', '241717', '241723', '241725', '241736', '241846', '241956', '241993', '242054', '242071', '242072', '242077', '242087', '242094', '242102', '242104', '242445', '242612', '242794', '242796', '242797', '242798', '242826', '242827']
    nosy_count = 10.0
    nosy_names = ['gvanrossum', 'rhettinger', 'pitrou', 'scoder', 'vstinner', 'lukasz.langa', 'python-dev', 'Ludovic.Gasc', 'martin.panter', 'yselivanov']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue24018'
    versions = ['Python 3.5']

    Activity

    1. scoder commented on Apr 20, 2015

      @scoder
      ContributorAuthor

      Currently, CPython tends to assume that generators are always implemented by a Python function that uses the "yield" keyword. However, it is absolutely possible to implement generators as a protocol by adding send(), throw() and close() methods to an iterator.

      The problem is that these will usually be rejected by code that needs to distinguish generators from other input, e.g. in asyncio, as this code will commonly do a type check against types.GeneratorType. Instead, it should check for the expected protocol. The best way to achieve this is to extend the existing ABCs with a Generator ABC that external generator implementations can register on.

      Related to bpo-24004 (asyncio). Asyncio could provide a backport copy of this for older Python versions.

      I assume this is considered a new feature that cannot be added to 3.4 anymore?

    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-featureA feature request or enhancement
      on Apr 20, 2015
    3. gvanrossum commented on Apr 20, 2015

      @gvanrossum
      Member

      It's missing tests. :-)

      Otherwise looks quite sensible.

      Also, shouldn't you override __subclasshook__ so you don't inherit it from Iterator?

    4. scoder commented on Apr 20, 2015

      @scoder
      ContributorAuthor

      Ok, sure. Here's a new patch that adds tests and docs.

    5. scoder commented on Apr 20, 2015

      @scoder
      ContributorAuthor

      Sorry, here's another doc fix.

    6. pitrou commented on Apr 20, 2015

      @pitrou
      Member

      Is it a problem that the check can't be done in a fast way from C code?

      Other than that, sounds good to me.

    7. self-assigned this
      on Apr 20, 2015
    8. rhettinger commented on Apr 21, 2015

      @rhettinger
      Contributor

      For the other ABCs, if you define the required abstract methods, you get working versions of all the mixin methods.

      In the case of the Generator ABC, throw() and close() are useless empty stub methods. In the other ABCs, we leave optional methods out entirely. A user should expect that if isinstance(g, Generator) is true that all of the ABC methods will work.

      Also, the return StopIteration in throw() doesn't seem correct. Shouldn't it raise the exception that was thrown?

          >>> def f():
                  yield x
      >>> g = f()
      >>> g.throw(KeyError)
      
          Traceback (most recent call last):
            File "<pyshell#11>", line 1, in <module>
              g.throw(KeyError)
            File "<pyshell#9>", line 1, in f
              def f():
          KeyError

      Ideally, there should be a practical example of where this ABC would be useful with anything other than a real generator.

    9. scoder commented on Apr 21, 2015

      @scoder
      ContributorAuthor

      Here's a new patch that addresses the review comments. I kept throw() and close() non-abstract and added an example to the tests instead that implements a minimal generator by inheriting these methods from the Generator base class, using it as a mixin. It only needs to implement send().

      I don't think it's unreasonable to assume that there are use cases where a generator that is implemented in a class instead of a yield-function does not require special cleanup actions in its close()/throw(). Or is it *required* that a generator stops working when close() is called?

      There are also iterators that raise StopIteration at some point to signal that they are temporarily exhausted, but then eventually restart returning values from their __next__() method when they have received more to return. Avoids recreating the iterator object after each exhaustion cycle.

      I extended the default implementation of close() to call throw(GeneratorExit), though, because that's how the protocol is defined. Unless users implement throw(), it won't make a difference for them. And if they do, they may even get away with not reimplementing close().

    10. scoder commented on Apr 21, 2015

      @scoder
      ContributorAuthor

      Is it a problem that the check can't be done in a fast way from C code?

      C code can still quickly special case the generator type in the positive case, and it will usually be interested in an exact type match anyway. Determining that an object is *not* (compatible with) a generator might lead to some degradation, but in most cases, at least in the interpreter core, this would be an error case anyway, so being slower here should rarely hurt.

    11. scoder commented on Apr 21, 2015

      @scoder
      ContributorAuthor

      Next question: should inspect.isgenerator() be changed? Or should its usages be replaced by isinstance(obj, Generator) ?

    12. vadmium commented on Apr 21, 2015

      @vadmium
      Member

      I agree that there is no big reason why we should force generators to stop working after close(). Your new default implementation of close() is probably the right thing too. I added a few new comments on Reitveld.

    13. scoder commented on Apr 21, 2015

      @scoder
      ContributorAuthor

      Good catch with the RuntimeError. Patch updated.

    14. scoder commented on Apr 21, 2015

      @scoder
      ContributorAuthor

      should inspect.isgenerator() be changed?

      Replying to myself, one thing that speaks against this approach is that "inspect" also has the functions "getgeneratorlocals()" and "getgeneratorstate()", which depend on "gen.gi_frame". Cython could emulate that, but normal user code usually can't. It's definitely not part of the Generator protocol but an implementation detail of GeneratorType.

    15. 17 remaining items

    16. rhettinger commented on Apr 27, 2015

      @rhettinger
      Contributor

      The latest patch looks good overall.

      Łukasz, assigning back to you.

    17. gvanrossum commented on May 3, 2015

      @gvanrossum
      Member

      Yeah, looks good -- Łuke, can you commit this?

    18. ambv commented on May 5, 2015

      @ambv
      Contributor

      Yup, will do.

    19. scoder commented on May 9, 2015

      @scoder
      ContributorAuthor

      This is blocking bpo-24017 (async/await syntax).

    20. gvanrossum commented on May 9, 2015

      @gvanrossum
      Member

      Ask Yury if he'll commit it for you. It's ready.

    21. python-dev commented on May 9, 2015

      python-devmannequin
      Mannequin

      New changeset ba5d7041e2f5 by Raymond Hettinger in branch 'default':
      Issue bpo-24018: Add a collections.Generator abstract base class.
      https://hg.python.org/cpython/rev/ba5d7041e2f5

    22. scoder commented on May 9, 2015

      @scoder
      ContributorAuthor

      Thanks! Minor grouch: it should say "collections.*abc*.Generator" in the NEWS entry.

    23. python-dev commented on May 9, 2015

      python-devmannequin
      Mannequin

      New changeset f7cc54086cd2 by Guido van Rossum in branch 'default':
      Fix news entry for bpo-24018.
      https://hg.python.org/cpython/rev/f7cc54086cd2

    24. gvanrossum commented on May 9, 2015

      @gvanrossum
      Member

      Fixed.

      On Fri, May 8, 2015 at 10:28 PM, Stefan Behnel <[email protected]>
      wrote:

      Stefan Behnel added the comment:

      Thanks! Minor grouch: it should say "collections.*abc*.Generator" in the
      NEWS entry.

      ----------


      Python tracker <[email protected]>
      <http://bugs.python.org/issue24018\>


    25. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions