Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ Paul Swartz
Ned Batchelder
Allison Kaptur
Laura Lindzey
Rahul Gopinath
Björn Mathis
Darius Bacon
42 changes: 19 additions & 23 deletions byterun/pyobj.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import collections
import inspect
import re
import types
import dis

import six
import sys

PY3, PY2 = six.PY3, not six.PY3

Expand All @@ -28,11 +31,12 @@ class Function(object):
'_vm', '_func',
]

def __init__(self, name, code, globs, defaults, closure, vm):
def __init__(self, name, code, globs, defaults, kwdefaults, closure, vm):
self._vm = vm
self.func_code = code
self.func_name = self.__name__ = name or code.co_name
self.func_defaults = tuple(defaults)
self.func_defaults = defaults \
if PY3 and sys.version_info.minor >= 6 else tuple(defaults)
self.func_globals = globs
self.func_locals = self._vm.frame.f_locals
self.__dict__ = {}
Expand Down Expand Up @@ -61,17 +65,18 @@ def __get__(self, instance, owner):
return self

def __call__(self, *args, **kwargs):
if PY2 and self.func_name in ["<setcomp>", "<dictcomp>", "<genexpr>"]:
if re.search(r'<(?:listcomp|setcomp|dictcomp|genexpr)>$', self.func_name):
# D'oh! http://bugs.python.org/issue19611 Py2 doesn't know how to
# inspect set comprehensions, dict comprehensions, or generator
# expressions properly. They are always functions of one argument,
# so just do the right thing.
# so just do the right thing. Py3.4 also would fail without this
# hack, for list comprehensions too. (Haven't checked for other 3.x.)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we check this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is another from #20 PR by @darius

assert len(args) == 1 and not kwargs, "Surprising comprehension!"
callargs = {".0": args[0]}
else:
callargs = inspect.getcallargs(self._func, *args, **kwargs)
frame = self._vm.make_frame(
self.func_code, callargs, self.func_globals, {}
self.func_code, callargs, self.func_globals, {}, self.func_closure
)
CO_GENERATOR = 32 # flag for "this code uses yield"
if self.func_code.co_flags & CO_GENERATOR:
Expand Down Expand Up @@ -135,8 +140,10 @@ def set(self, value):


class Frame(object):
def __init__(self, f_code, f_globals, f_locals, f_back):
def __init__(self, f_code, f_globals, f_locals, f_closure, f_back):
self.f_code = f_code
if sys.version_info >= (3, 4):
self.opcodes = list(dis.get_instructions(self.f_code))
self.f_globals = f_globals
self.f_locals = f_locals
self.f_back = f_back
Expand All @@ -151,24 +158,13 @@ def __init__(self, f_code, f_globals, f_locals, f_back):
self.f_lineno = f_code.co_firstlineno
self.f_lasti = 0

if f_code.co_cellvars:
self.cells = {}
if not f_back.cells:
f_back.cells = {}
for var in f_code.co_cellvars:
# Make a cell for the variable in our locals, or None.
cell = Cell(self.f_locals.get(var))
f_back.cells[var] = self.cells[var] = cell
else:
self.cells = None

self.cells = {} if f_code.co_cellvars or f_code.co_freevars else None
for var in f_code.co_cellvars:
# Make a cell for the variable in our locals, or None.
self.cells[var] = Cell(self.f_locals.get(var))
if f_code.co_freevars:
if not self.cells:
self.cells = {}
for var in f_code.co_freevars:
assert self.cells is not None
assert f_back.cells, "f_back.cells: %r" % (f_back.cells,)
self.cells[var] = f_back.cells[var]
assert len(f_code.co_freevars) == len(f_closure)
self.cells.update(zip(f_code.co_freevars, f_closure))

self.block_stack = []
self.generator = None
Expand Down
Loading