Skip to content

GitLab

  • Menu
Projects Groups Snippets
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • pypy pypy
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 653
    • Issues 653
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 13
    • Merge requests 13
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Incidents
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • PyPy
  • pypypypy
  • Issues
  • #2034

Closed
Open
Created Apr 24, 2015 by Bitbucket Importer@bitbucket_importerMaintainer

PyPy Regression with Python on Iterable expansions

Created originally on Bitbucket by pedrorodriguez (Pedro Rodriguez)

I am the main developer on github.com/EntilZha/ScalaFunctional and in working on it I found a regression with Python. I don't know if it is an intended regression, but it caused some unexpected behavior which I was able to narrow down. If you want the full explanation, it is on the issue on the project here: https://github.com/EntilZha/ScalaFunctional/issues/25

Below is a minimal code example showing the regression between pypy and python. The primary problem is how pypy is doing expansions of iterables (list(), set(), dict(), ...). When those are expanded pypy will call __iter__, then __len__. Python will only call __iter__.

#!python

from collections import Iterable

class A(object):
    def __init__(self, seq):
        self.l = seq
    def __getitem__(self, item):
        print "DEBUG:getitem called"
        return self.l[item]
    def __iter__(self):
        print "DEBUG:iter called"
        return iter(self.l)
    def __len__(self):
        print "DEBUG:len called"
        if isinstance(self.l, Iterable):
            self.l = list(self.l)
        return len(self.l)

class B(object):
    def __init__(self, seq):
        self.l = seq
    def __iter__(self):
        print "DEBUG:iter called"
        return iter(self.l)

# set interchangable with list/dict
print "Calling set(A([1, 2]))"
a = A([1, 2])
print set(a)


print "Calling set(B([1, 2]))"
b = B([1, 2])
print set(b)

print "Calling union"
s = set([1, 2, 3]).union([4, 5])
c = A(iter(s))
print set(c)
#!python
$ python iterable.py
Calling set(A([1, 2]))
DEBUG:iter called
set([1, 2])
Calling set(B([1, 2]))
DEBUG:iter called
set([1, 2])
Calling union
DEBUG:iter called
set([1, 2, 3, 4, 5])
$ pypy iterable.py
Calling set(A([1, 2]))
DEBUG:len called
DEBUG:iter called
[1, 2]
Calling set(B([1, 2]))
DEBUG:iter called
set([1, 2])
Calling union
DEBUG:iter called
DEBUG:len called
set([])

Since I am unfamiliar with pypy I don't know if the regression is intended or unintended.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking