Author: Armin Rigo <[email protected]>
Branch: py3.5-corowrapper
Changeset: r87179:4411daaf0ffe
Date: 2016-09-17 17:35 +0200
http://bitbucket.org/pypy/pypy/changeset/4411daaf0ffe/
Log: Setting __name__ on generator-iterator objects (uh?)
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -36,6 +36,7 @@
'closure?[*]',
'defs_w?[*]',
'name?',
+ 'qualname?',
'w_kw_defs?']
w_kw_defs = None
@@ -117,7 +118,7 @@
for i in funccallunrolling:
if i < nargs:
new_frame.locals_cells_stack_w[i] = args_w[i]
- return new_frame.run()
+ return new_frame.run(self.name, self.qualname)
elif nargs >= 1 and fast_natural_arity == Code.PASSTHROUGHARGS1:
assert isinstance(code, gateway.BuiltinCodePassThroughArguments1)
return code.funcrun_obj(self, args_w[0],
@@ -184,7 +185,7 @@
w_arg = frame.peekvalue(nargs-1-i)
new_frame.locals_cells_stack_w[i] = w_arg
- return new_frame.run()
+ return new_frame.run(self.name, self.qualname)
@jit.unroll_safe
def _flat_pycall_defaults(self, code, nargs, frame, defs_to_load):
@@ -201,7 +202,7 @@
for j in xrange(start, ndefs):
new_frame.locals_cells_stack_w[i] = self.defs_w[j]
i += 1
- return new_frame.run()
+ return new_frame.run(self.name, self.qualname)
def getdict(self, space):
if self.w_func_dict is None:
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -23,6 +23,7 @@
self.register_finalizer(self.space)
def get_name(self):
+ # 'name' is a byte string that is valid utf-8
if self._name is not None:
return self._name
elif self.pycode is None:
@@ -31,9 +32,10 @@
return self.pycode.co_name
def get_qualname(self):
+ # 'qualname' is a unicode string
if self._qualname is not None:
return self._qualname
- return self.get_name()
+ return self.get_name().decode('utf-8')
def descr__repr__(self, space):
addrstring = self.getaddrstring(space)
@@ -292,11 +294,27 @@
return space.w_None
def descr__name__(self, space):
- return space.wrap(self.get_name())
+ return space.wrap(self.get_name().decode('utf-8'))
+
+ def descr_set__name__(self, space, w_name):
+ if space.isinstance_w(w_name, space.w_unicode):
+ self._name = space.str_w(w_name)
+ else:
+ raise oefmt(space.w_TypeError,
+ "__name__ must be set to a string object")
def descr__qualname__(self, space):
return space.wrap(self.get_qualname())
+ def descr_set__qualname__(self, space, w_name):
+ try:
+ self._qualname = space.unicode_w(w_name)
+ except OperationError as e:
+ if e.match(space, space.w_TypeError):
+ raise oefmt(space.w_TypeError,
+ "__qualname__ must be set to a string object")
+ raise
+
def _finalize_(self):
# This is only called if the CO_YIELD_INSIDE_TRY flag is set
# on the code object. If the frame is still not finished and
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -265,7 +265,7 @@
args.parse_into_scope(None, fresh_frame.locals_cells_stack_w,
func.name,
sig, func.defs_w, func.w_kw_defs)
fresh_frame.init_cells()
- return frame.run()
+ return frame.run(func.name, func.qualname)
def funcrun_obj(self, func, w_obj, args):
frame = self.space.createframe(self, func.w_func_globals,
@@ -277,7 +277,7 @@
args.parse_into_scope(w_obj, fresh_frame.locals_cells_stack_w,
func.name,
sig, func.defs_w, func.w_kw_defs)
fresh_frame.init_cells()
- return frame.run()
+ return frame.run(func.name, func.qualname)
def getvarnames(self):
return self.co_varnames
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -244,22 +244,26 @@
return (self.getcode().co_flags & (pycode.CO_COROUTINE |
pycode.CO_GENERATOR)) != 0
- def run(self):
+ def run(self, name=None, qualname=None):
"""Start this frame's execution."""
if self._is_generator_or_coroutine():
- if self.getcode().co_flags & pycode.CO_COROUTINE:
- from pypy.interpreter.generator import Coroutine
- gen = Coroutine(self)
- else:
- from pypy.interpreter.generator import GeneratorIterator
- gen = GeneratorIterator(self)
- if self.space.config.translation.rweakref:
- self.f_generator_wref = rweakref.ref(gen)
- else:
- self.f_generator_nowref = gen
- return self.space.wrap(gen)
+ return self.initialize_as_generator(name, qualname)
else:
return self.execute_frame()
+ run._always_inline_ = True
+
+ def initialize_as_generator(self, name, qualname):
+ if self.getcode().co_flags & pycode.CO_COROUTINE:
+ from pypy.interpreter.generator import Coroutine
+ gen = Coroutine(self, name, qualname)
+ else:
+ from pypy.interpreter.generator import GeneratorIterator
+ gen = GeneratorIterator(self, name, qualname)
+ if self.space.config.translation.rweakref:
+ self.f_generator_wref = rweakref.ref(gen)
+ else:
+ self.f_generator_nowref = gen
+ return self.space.wrap(gen)
def execute_frame(self, in_generator=None, w_arg_or_err=None):
"""Execute this frame. Main entry point to the interpreter.
diff --git a/pypy/interpreter/test/test_function.py
b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -32,6 +32,12 @@
assert f.__qualname__ == 'qualname'
raises(TypeError, "f.__qualname__ = b'name'")
+ def test_qualname_method(self):
+ class A:
+ def f(self):
+ pass
+ assert A.f.__qualname__ == 'test_qualname_method.<locals>.A.f'
+
def test_annotations(self):
def f(): pass
ann = f.__annotations__
diff --git a/pypy/interpreter/test/test_generator.py
b/pypy/interpreter/test/test_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/test_generator.py
@@ -379,6 +379,22 @@
assert False, 'Expected StopIteration'
"""
+ def test_set_name_qualname(self):
+ class A:
+ def f(self):
+ yield 5
+ g = A().f()
+ assert g.__name__ == "f"
+ assert g.__qualname__ == "test_set_name_qualname.<locals>.A.f"
+ g.__name__ = "h.i"
+ g.__qualname__ = "j.k"
+ assert g.__name__ == "h.i"
+ assert g.__qualname__ == "j.k"
+ raises(TypeError, "g.__name__ = 42")
+ raises(TypeError, "g.__qualname__ = 42")
+ raises((TypeError, AttributeError), "del g.__name__")
+ raises((TypeError, AttributeError), "del g.__qualname__")
+
def test_should_not_inline(space):
from pypy.interpreter.generator import should_not_inline
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -796,8 +796,10 @@
gi_frame = GetSetProperty(GeneratorIterator.descr_gicr_frame),
gi_code = interp_attrproperty_w('pycode', cls=GeneratorIterator),
gi_yieldfrom=interp_attrproperty_w('w_yielded_from',
cls=GeneratorIterator),
- __name__ = GetSetProperty(GeneratorIterator.descr__name__),
- __qualname__ = GetSetProperty(GeneratorIterator.descr__qualname__),
+ __name__ = GetSetProperty(GeneratorIterator.descr__name__,
+ GeneratorIterator.descr_set__name__),
+ __qualname__ = GetSetProperty(GeneratorIterator.descr__qualname__,
+ GeneratorIterator.descr_set__qualname__),
__weakref__ = make_weakref_descr(GeneratorIterator),
)
assert not GeneratorIterator.typedef.acceptable_as_base_class # no __new__
@@ -824,8 +826,10 @@
cr_frame = GetSetProperty(Coroutine.descr_gicr_frame),
cr_code = interp_attrproperty_w('pycode', cls=Coroutine),
cr_await = interp_attrproperty_w('w_yielded_from', cls=Coroutine),
- __name__ = GetSetProperty(Coroutine.descr__name__),
- __qualname__ = GetSetProperty(Coroutine.descr__qualname__),
+ __name__ = GetSetProperty(Coroutine.descr__name__,
+ Coroutine.descr_set__name__),
+ __qualname__ = GetSetProperty(Coroutine.descr__qualname__,
+ Coroutine.descr_set__qualname__),
__weakref__ = make_weakref_descr(Coroutine),
)
assert not Coroutine.typedef.acceptable_as_base_class # no __new__
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit