[pypy-commit] pypy py3.5: Detail: CO_GENERATOR is set in addition to CO_COROUTINE in some (nonsensical imho) cases
Author: Armin Rigo
Branch: py3.5
Changeset: r89463:e0ba73be669b
Date: 2017-01-10 09:19 +0100
http://bitbucket.org/pypy/pypy/changeset/e0ba73be669b/
Log:Detail: CO_GENERATOR is set in addition to CO_COROUTINE in some
(nonsensical imho) cases
diff --git a/pypy/interpreter/astcompiler/codegen.py
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -375,7 +375,7 @@
l += 1
return l
-def _visit_function(self, func, function_code_generator, extra_flag):
+def _visit_function(self, func, function_code_generator):
self.update_position(func.lineno, True)
# Load decorators first, but apply them after the function is created.
self.visit_sequence(func.decorator_list)
@@ -392,7 +392,6 @@
oparg |= num_annotations << 16
code, qualname = self.sub_scope(function_code_generator, func.name,
func, func.lineno)
-code.co_flags |= extra_flag
self._make_function(code, oparg, qualname=qualname)
# Apply decorators.
if func.decorator_list:
@@ -401,11 +400,10 @@
self.name_op(func.name, ast.Store)
def visit_FunctionDef(self, func):
-self._visit_function(func, FunctionCodeGenerator, 0)
+self._visit_function(func, FunctionCodeGenerator)
def visit_AsyncFunctionDef(self, func):
-self._visit_function(func, AsyncFunctionCodeGenerator,
- consts.CO_COROUTINE)
+self._visit_function(func, AsyncFunctionCodeGenerator)
def visit_Lambda(self, lam):
self.update_position(lam.lineno)
@@ -1569,6 +1567,10 @@
for i in range(start, len(func.body)):
func.body[i].walkabout(self)
+def _get_code_flags(self):
+flags = AbstractFunctionCodeGenerator._get_code_flags(self)
+return flags | consts.CO_COROUTINE
+
class LambdaCodeGenerator(AbstractFunctionCodeGenerator):
def _compile(self, lam):
diff --git a/pypy/interpreter/astcompiler/symtable.py
b/pypy/interpreter/astcompiler/symtable.py
--- a/pypy/interpreter/astcompiler/symtable.py
+++ b/pypy/interpreter/astcompiler/symtable.py
@@ -317,7 +317,11 @@
yield_node.col_offset)
def note_await(self, await_node):
-pass
+# Compatibility with CPython 3.5: set the CO_GENERATOR flag in
+# addition to the CO_COROUTINE flag if the function uses the
+# "await" keyword. Don't do it if the function does not. In
+# that case, CO_GENERATOR is ignored anyway.
+self.is_generator = True
class ClassScope(Scope):
diff --git a/pypy/interpreter/astcompiler/test/test_symtable.py
b/pypy/interpreter/astcompiler/test/test_symtable.py
--- a/pypy/interpreter/astcompiler/test/test_symtable.py
+++ b/pypy/interpreter/astcompiler/test/test_symtable.py
@@ -364,6 +364,13 @@
scp = self.func_scope(input)
scp = self.func_scope("def f():\nreturn\nyield x")
+def test_async_def(self):
+# CPython compatibility only; "is_generator" is otherwise ignored
+scp = self.func_scope("async def f(): pass")
+assert not scp.is_generator
+scp = self.func_scope("async def f(): await 5")
+assert scp.is_generator
+
def test_yield_inside_try(self):
scp = self.func_scope("def f(): yield x")
assert not scp.has_yield_inside_try
___
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: fix a test for pypy
Author: Armin Rigo Branch: py3.5 Changeset: r89462:85928a9ccfac Date: 2017-01-10 08:54 +0100 http://bitbucket.org/pypy/pypy/changeset/85928a9ccfac/ Log:fix a test for pypy diff --git a/lib-python/3/test/test_dis.py b/lib-python/3/test/test_dis.py --- a/lib-python/3/test/test_dis.py +++ b/lib-python/3/test/test_dis.py @@ -230,6 +230,9 @@ 26 RETURN_VALUE """ +# XXX PyPy change: the original output has SETUP_EXCEPT, SETUP_FINALLY, +# POP_EXCEPT, END_FINALLY in that order. The pops don't match the +# setups. In PyPy the POP_EXCEPT is moved after the END_FINALLY. dis_traceback = """\ %3d 0 SETUP_EXCEPT12 (to 15) @@ -247,18 +250,18 @@ 25 POP_TOP 26 STORE_FAST 0 (e) 29 POP_TOP - 30 SETUP_FINALLY 14 (to 47) + 30 SETUP_FINALLY 13 (to 46) %3d 33 LOAD_FAST0 (e) 36 LOAD_ATTR1 (__traceback__) 39 STORE_FAST 1 (tb) 42 POP_BLOCK - 43 POP_EXCEPT - 44 LOAD_CONST 0 (None) ->> 47 LOAD_CONST 0 (None) - 50 STORE_FAST 0 (e) - 53 DELETE_FAST 0 (e) - 56 END_FINALLY + 43 LOAD_CONST 0 (None) +>> 46 LOAD_CONST 0 (None) + 49 STORE_FAST 0 (e) + 52 DELETE_FAST 0 (e) + 55 END_FINALLY + 56 POP_EXCEPT 57 JUMP_FORWARD 1 (to 61) >> 60 END_FINALLY ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Fix remaining tests
Author: Armin Rigo Branch: py3.5 Changeset: r89464:aa6799139d13 Date: 2017-01-10 09:49 +0100 http://bitbucket.org/pypy/pypy/changeset/aa6799139d13/ Log:Fix remaining tests diff --git a/lib-python/3/test/test_dis.py b/lib-python/3/test/test_dis.py --- a/lib-python/3/test/test_dis.py +++ b/lib-python/3/test/test_dis.py @@ -414,13 +414,15 @@ +# CPython 3.5 gives a stack size of 4 whereas it really needs only 3 +# http://bugs.python.org/issue24340 code_info_code_info = """\ Name: code_info Filename: (.*) Argument count:1 Kw-only arguments: 0 Number of locals: 1 -Stack size:4 +Stack size:(4|3) Flags: OPTIMIZED, NEWLOCALS, NOFREE, 0x10 Constants: 0: %r @@ -539,13 +541,15 @@ async for a in b: pass async with c as d: pass +# CPython 3.5 gives a stack size of 17 whereas it really needs only 7 +# http://bugs.python.org/issue24340 code_info_async_def = """\ Name: async_def Filename: (.*) Argument count:0 Kw-only arguments: 0 Number of locals: 2 -Stack size:17 +Stack size:(17|7) Flags: OPTIMIZED, NEWLOCALS, GENERATOR, NOFREE, COROUTINE Constants: 0: None @@ -714,13 +718,15 @@ Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=28, starts_line=None, is_jump_target=False), ] +# Regenerated for PyPy (difference: some extra dead jumps and jumps-to-jumps +# in PyPy, not worth optimizing away imho) expected_opinfo_jumpy = [ - Instruction(opname='SETUP_LOOP', opcode=120, arg=68, argval=71, argrepr='to 71', offset=0, starts_line=3, is_jump_target=False), + Instruction(opname='SETUP_LOOP', opcode=120, arg=74, argval=77, argrepr='to 77', offset=0, starts_line=3, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=3, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=6, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=9, starts_line=None, is_jump_target=False), Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=12, starts_line=None, is_jump_target=False), - Instruction(opname='FOR_ITER', opcode=93, arg=44, argval=60, argrepr='to 60', offset=13, starts_line=None, is_jump_target=True), + Instruction(opname='FOR_ITER', opcode=93, arg=50, argval=66, argrepr='to 66', offset=13, starts_line=None, is_jump_target=True), Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=19, starts_line=4, is_jump_target=False), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=22, starts_line=None, is_jump_target=False), @@ -729,89 +735,93 @@ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=29, starts_line=5, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=32, starts_line=None, is_jump_target=False), Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=35, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=44, argval=44, argrepr='', offset=38, starts_line=None, is_jump_target=False), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=47, argval=47, argrepr='', offset=38, starts_line=None, is_jump_target=False), Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=13, argval=13, argrepr='', offset=41, starts_line=6, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=44, starts_line=7, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=47, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=50, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=13, argval=13, argrepr='', offset=53, starts_line=None, is_jump_target=False), - Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=56, starts_line=8, is_jump_target=False), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=13, argval=13, argrepr='', offset=57, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=60, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=61, starts_line=10, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I c
[pypy-commit] pypy py3.5: More strange cases of bytes.__mod__
Author: Armin Rigo Branch: py3.5 Changeset: r89465:a003fe61afd9 Date: 2017-01-10 10:28 +0100 http://bitbucket.org/pypy/pypy/changeset/a003fe61afd9/ Log:More strange cases of bytes.__mod__ diff --git a/pypy/objspace/std/formatting.py b/pypy/objspace/std/formatting.py --- a/pypy/objspace/std/formatting.py +++ b/pypy/objspace/std/formatting.py @@ -583,12 +583,22 @@ # we check directly for dict to avoid obscure checking # in simplest case if space.isinstance_w(w_values, space.w_dict) or \ - (space.lookup(w_values, '__getitem__') and - not space.isinstance_w(w_values, space.w_unicode)): + _looks_like_a_mapping(space, w_values, fmt_type): return format(space, w_format, [w_values], w_values, fmt_type) else: return format(space, w_format, [w_values], None, fmt_type) +def _looks_like_a_mapping(space, w_x, fmt_type): +if not space.lookup(w_x, '__getitem__'): +return False +if space.isinstance_w(w_x, space.w_unicode): +return False +if fmt_type != FORMAT_UNICODE: # (S6) in http://bugs.python.org/issue28885 +if (space.isinstance_w(w_x, space.w_bytes) or +space.isinstance_w(w_x, space.w_bytearray)): +return False +return True + # # Formatting helpers diff --git a/pypy/objspace/std/test/test_bytearrayobject.py b/pypy/objspace/std/test/test_bytearrayobject.py --- a/pypy/objspace/std/test/test_bytearrayobject.py +++ b/pypy/objspace/std/test/test_bytearrayobject.py @@ -604,6 +604,17 @@ def test_format_bytes(self): assert bytearray(b'<%s>') % b'abc' == b'' +def test_formatting_not_tuple(self): +class mydict(dict): +pass +xxx = bytearray(b'xxx') +assert xxx % mydict() == xxx +assert xxx % [] == xxx # [] considered as a mapping(!) +raises(TypeError, "xxx % 'foo'") +raises(TypeError, "xxx % b'foo'") +raises(TypeError, "xxx % bytearray()") +raises(TypeError, "xxx % 53") + def test___alloc__(self): # pypy: always returns len()+1; cpython: may be bigger assert bytearray(b'123456').__alloc__() >= 7 diff --git a/pypy/objspace/std/test/test_bytesobject.py b/pypy/objspace/std/test/test_bytesobject.py --- a/pypy/objspace/std/test/test_bytesobject.py +++ b/pypy/objspace/std/test/test_bytesobject.py @@ -176,6 +176,16 @@ def test_format_bytes(self): assert b'<%s>' % b'abc' == b'' +def test_formatting_not_tuple(self): +class mydict(dict): +pass +assert b'xxx' % mydict() == b'xxx' +assert b'xxx' % [] == b'xxx' # [] considered as a mapping(!) +raises(TypeError, "b'xxx' % 'foo'") +raises(TypeError, "b'xxx' % b'foo'") +raises(TypeError, "b'xxx' % bytearray()") +raises(TypeError, "b'xxx' % 53") + def test_split(self): assert b"".split() == [] assert b"".split(b'x') == [b''] diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -912,6 +912,16 @@ # Printable character assert '%r' % chr(0xe9) == "'\xe9'" +def test_formatting_not_tuple(self): +class mydict(dict): +pass +assert 'xxx' % mydict() == 'xxx' +assert 'xxx' % b'foo' == 'xxx' # b'foo' considered as a mapping(!) +assert 'xxx' % bytearray() == 'xxx' # same +assert 'xxx' % [] == 'xxx' # [] considered as a mapping(!) +raises(TypeError, "'xxx' % 'foo'") +raises(TypeError, "'xxx' % 53") + def test_str_subclass(self): class Foo9(str): def __str__(self): ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: test and fix
Author: Armin Rigo
Branch: py3.5
Changeset: r89466:9124eb47aa9d
Date: 2017-01-10 10:56 +0100
http://bitbucket.org/pypy/pypy/changeset/9124eb47aa9d/
Log:test and fix
diff --git a/pypy/objspace/std/objectobject.py
b/pypy/objspace/std/objectobject.py
--- a/pypy/objspace/std/objectobject.py
+++ b/pypy/objspace/std/objectobject.py
@@ -18,25 +18,6 @@
import copyreg
return copyreg._reduce_ex(obj, proto)
-def _getnewargs(obj):
-
-try:
-getnewargs = obj.__getnewargs_ex__
-except AttributeError:
-try:
-getnewargs = obj.__getnewargs__
-except AttributeError:
-args = ()
-else:
-args = getnewargs()
-kwargs = None
-else:
-args, kwargs = getnewargs()
-
-if not isinstance(args, tuple):
-raise TypeError("__getnewargs__ should return a tuple")
-return args, kwargs
-
def _getstate(obj):
cls = obj.__class__
@@ -60,13 +41,13 @@
state = getstate()
return state
-def reduce_2(obj, proto):
+def reduce_2(obj, proto, args, kwargs):
cls = obj.__class__
import copyreg
-args, kwargs = _getnewargs(obj)
-
+if not isinstance(args, tuple):
+raise TypeError("__getnewargs__ should return a tuple")
if not kwargs:
newobj = copyreg.__newobj__
args2 = (cls,) + args
@@ -187,7 +168,18 @@
def descr__reduce__(space, w_obj, proto=0):
w_proto = space.wrap(proto)
if proto >= 2:
-return reduce_2(space, w_obj, w_proto)
+w_descr = space.lookup(w_obj, '__getnewargs_ex__')
+if w_descr is not None:
+w_result = space.get_and_call_function(w_descr, w_obj)
+w_args, w_kwargs = space.fixedview(w_result, 2)
+else:
+w_descr = space.lookup(w_obj, '__getnewargs__')
+if w_descr is not None:
+w_args = space.get_and_call_function(w_descr, w_obj)
+else:
+w_args = space.newtuple([])
+w_kwargs = space.w_None
+return reduce_2(space, w_obj, w_proto, w_args, w_kwargs)
return reduce_1(space, w_obj, w_proto)
@unwrap_spec(proto=int)
diff --git a/pypy/objspace/std/test/test_obj.py
b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -75,6 +75,20 @@
(NamedInt, ('Name',), dict(value=42)),
dict(_name='Name'), None, None)
+def test_reduce_ex_does_getattr(self):
+seen = []
+class X:
+def __getattribute__(self, name):
+seen.append(name)
+return object.__getattribute__(self, name)
+X().__reduce_ex__(2)
+# it is the case at least on CPython 3.5.2, like PyPy:
+assert '__reduce__' in seen
+# but these methods, which are also called, are not looked up
+# with getattr:
+assert '__getnewargs__' not in seen
+assert '__getnewargs_ex__' not in seen
+
def test_default_format(self):
class x(object):
def __str__(self):
___
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: minimal test for one thing that changed in unicodedata 8.0.0
Author: Armin Rigo Branch: Changeset: r89467:5b5373c38aed Date: 2017-01-10 11:18 +0100 http://bitbucket.org/pypy/pypy/changeset/5b5373c38aed/ Log:minimal test for one thing that changed in unicodedata 8.0.0 diff --git a/rpython/rlib/unicodedata/test/test_unicodedata.py b/rpython/rlib/unicodedata/test/test_unicodedata.py --- a/rpython/rlib/unicodedata/test/test_unicodedata.py +++ b/rpython/rlib/unicodedata/test/test_unicodedata.py @@ -5,7 +5,8 @@ import py from rpython.rlib.unicodedata import ( -unicodedb_3_2_0, unicodedb_5_2_0, unicodedb_6_0_0, unicodedb_6_2_0) +unicodedb_3_2_0, unicodedb_5_2_0, unicodedb_6_0_0, unicodedb_6_2_0, +unicodedb_8_0_0) class TestUnicodeData(object): @@ -141,3 +142,9 @@ def test_islower(self): assert unicodedb_6_2_0.islower(0x2177) + + +class TestUnicodeData800(object): +def test_changed_in_version_8(self): +assert unicodedb_6_2_0.toupper_full(0x025C) == [0x025C] +assert unicodedb_8_0_0.toupper_full(0x025C) == [0xA7AB] ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Bah, the version number of the unicode database we use must be fixed
Author: Armin Rigo
Branch: py3.5
Changeset: r89468:a3395285a8ad
Date: 2017-01-10 11:19 +0100
http://bitbucket.org/pypy/pypy/changeset/a3395285a8ad/
Log:Bah, the version number of the unicode database we use must be fixed
here too. Change the logic so that a single place is enough.
diff --git a/pypy/module/unicodedata/__init__.py
b/pypy/module/unicodedata/__init__.py
--- a/pypy/module/unicodedata/__init__.py
+++ b/pypy/module/unicodedata/__init__.py
@@ -3,7 +3,8 @@
# This is the default unicodedb used in various places:
# - the unicode type
# - the regular expression engine
-from rpython.rlib.unicodedata import unicodedb_6_1_0 as unicodedb
+from pypy.module.unicodedata.interp_ucd import ucd as _ucd
+unicodedb = _ucd._unicodedb
# to get information about individual unicode chars look at:
# http://www.fileformat.info/info/unicode/char/search.htm
diff --git a/pypy/module/unicodedata/interp_ucd.py
b/pypy/module/unicodedata/interp_ucd.py
--- a/pypy/module/unicodedata/interp_ucd.py
+++ b/pypy/module/unicodedata/interp_ucd.py
@@ -77,6 +77,7 @@
class UCD(W_Root):
def __init__(self, unicodedb):
+self._unicodedb = unicodedb
self._lookup = unicodedb.lookup_with_alias
self._lookup_named_sequence = unicodedb.lookup_named_sequence
self._name = unicodedb.name
diff --git a/pypy/objspace/std/test/test_unicodeobject.py
b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -234,6 +234,9 @@
assert ('\u019b\u1d00\u1d86\u0221\u1fb7'.capitalize() ==
'\u019b\u1d00\u1d86\u0221\u1fb7')
+def test_changed_in_unicodedata_version_8(self):
+assert u'\u025C'.upper() == u'\uA7AB'
+
def test_isprintable(self):
assert "".isprintable()
assert " ".isprintable()
___
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Backed out changeset 83e15a9ac426
Author: Armin Rigo Branch: py3.5 Changeset: r89469:b4a03f3d70b6 Date: 2017-01-10 12:07 +0100 http://bitbucket.org/pypy/pypy/changeset/b4a03f3d70b6/ Log:Backed out changeset 83e15a9ac426 It seems that --version was never actually changed to print to stderr (it prints to stdout in 3.3, 3.4 and 3.5) diff --git a/lib-python/3/test/test_ensurepip.py b/lib-python/3/test/test_ensurepip.py --- a/lib-python/3/test/test_ensurepip.py +++ b/lib-python/3/test/test_ensurepip.py @@ -310,7 +310,7 @@ @requires_usable_pip def test_bootstrap_version(self): -with test.support.captured_stderr() as stdout: +with test.support.captured_stdout() as stdout: with self.assertRaises(SystemExit): ensurepip._main(["--version"]) result = stdout.getvalue().strip() @@ -335,7 +335,7 @@ class TestUninstallationMainFunction(EnsurepipMixin, unittest.TestCase): def test_uninstall_version(self): -with test.support.captured_stderr() as stdout: +with test.support.captured_stdout() as stdout: with self.assertRaises(SystemExit): ensurepip._uninstall._main(["--version"]) result = stdout.getvalue().strip() ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: fix test
Author: Armin Rigo
Branch: py3.5
Changeset: r89470:783976b8ae44
Date: 2017-01-10 12:17 +0100
http://bitbucket.org/pypy/pypy/changeset/783976b8ae44/
Log:fix test
diff --git a/pypy/module/_io/test/test_fileio.py
b/pypy/module/_io/test/test_fileio.py
--- a/pypy/module/_io/test/test_fileio.py
+++ b/pypy/module/_io/test/test_fileio.py
@@ -155,10 +155,17 @@
f.seek(0)
m = memoryview(bytearray(b"helloworld"))
assert f.readinto(m) == 10
+#
exc = raises(TypeError, f.readinto, u"hello")
-assert str(exc.value) == "must be read-write buffer, not str"
+msg = str(exc.value)
+print(msg)
+assert " read-write b" in msg and msg.endswith(", not str")
+#
exc = raises(TypeError, f.readinto, memoryview(b"hello"))
-assert str(exc.value) == "must be read-write buffer, not memoryview"
+msg = str(exc.value)
+print(msg)
+assert " read-write b" in msg and msg.endswith(", not memoryview")
+#
f.close()
assert a == b'a\nb\nc\0\0\0\0\0'
#
___
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Check that the 'opener' of the file constructors don't return a negative fd
Author: Armin Rigo Branch: py3.5 Changeset: r89471:f9c35809153c Date: 2017-01-10 12:20 +0100 http://bitbucket.org/pypy/pypy/changeset/f9c35809153c/ Log:Check that the 'opener' of the file constructors don't return a negative fd diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py --- a/pypy/module/_io/interp_fileio.py +++ b/pypy/module/_io/interp_fileio.py @@ -194,6 +194,11 @@ w_fd = space.call_function(w_opener, w_name, space.wrap(flags)) try: self.fd = space.int_w(w_fd) +if self.fd < 0: +# The opener returned a negative result instead +# of raising an exception +raise oefmt(space.w_ValueError, +"opener returned %d", self.fd) fd_is_own = True except OperationError as e: if not e.match(space, space.w_TypeError): diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py --- a/pypy/module/_io/test/test_fileio.py +++ b/pypy/module/_io/test/test_fileio.py @@ -282,6 +282,12 @@ if fd1 != fd2: raises(OSError, posix.close, fd1) +def test_opener_negative(self): +import _io +def opener(*args): +return -1 +raises(ValueError, _io.FileIO, "foo", 'r', opener=opener) + def test_flush_at_exit(): from pypy import conftest ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: fix test if run alone
Author: Armin Rigo Branch: py3.5 Changeset: r89472:e10143ffba30 Date: 2017-01-10 12:37 +0100 http://bitbucket.org/pypy/pypy/changeset/e10143ffba30/ Log:fix test if run alone diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py --- a/pypy/module/_io/test/test_fileio.py +++ b/pypy/module/_io/test/test_fileio.py @@ -151,6 +151,9 @@ import _io a = bytearray(b'x' * 10) f = _io.FileIO(self.tmpfile, 'r+') +f.seek(5) +f.write(b'\x00' * 5) +f.seek(0) assert f.readinto(a) == 10 f.seek(0) m = memoryview(bytearray(b"helloworld")) ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: readinto1(), and fix expected error messages for readinto() test
Author: Armin Rigo
Branch: py3.5
Changeset: r89473:26d691d3df32
Date: 2017-01-10 12:42 +0100
http://bitbucket.org/pypy/pypy/changeset/26d691d3df32/
Log:readinto1(), and fix expected error messages for readinto() test
diff --git a/pypy/module/_io/interp_bufferedio.py
b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -107,18 +107,25 @@
self._unsupportedoperation(space, "detach")
def readinto_w(self, space, w_buffer):
+return self._readinto(space, w_buffer, "read")
+
+def readinto1_w(self, space, w_buffer):
+return self._readinto(space, w_buffer, "read1")
+
+def _readinto(self, space, w_buffer, methodname):
rwbuffer = space.getarg_w('w*', w_buffer)
length = rwbuffer.getlength()
-w_data = space.call_method(self, "read", space.wrap(length))
+w_data = space.call_method(self, methodname, space.wrap(length))
if not space.isinstance_w(w_data, space.w_str):
-raise oefmt(space.w_TypeError, "read() should return bytes")
+raise oefmt(space.w_TypeError, "%s() should return bytes",
+methodname)
data = space.bytes_w(w_data)
if len(data) > length:
raise oefmt(space.w_ValueError,
-"read() returned too much data: "
+"%s() returned too much data: "
"%d bytes requested, %d returned",
-length, len(data))
+methodname, length, len(data))
rwbuffer.setslice(0, data)
return space.wrap(len(data))
@@ -144,6 +151,7 @@
write = interp2app(W_BufferedIOBase.write_w),
detach = interp2app(W_BufferedIOBase.detach_w),
readinto = interp2app(W_BufferedIOBase.readinto_w),
+readinto1 = interp2app(W_BufferedIOBase.readinto1_w),
)
class RawBuffer(Buffer):
diff --git a/pypy/module/_io/interp_bytesio.py
b/pypy/module/_io/interp_bytesio.py
--- a/pypy/module/_io/interp_bytesio.py
+++ b/pypy/module/_io/interp_bytesio.py
@@ -83,9 +83,6 @@
limit = convert_size(space, w_limit)
return space.newbytes(self.readline(limit))
-def read1_w(self, space, w_size):
-return self.read_w(space, w_size)
-
def readinto_w(self, space, w_buffer):
self._check_closed(space)
rwbuffer = space.getarg_w('w*', w_buffer)
@@ -203,9 +200,10 @@
__init__ = interp2app(W_BytesIO.descr_init),
read = interp2app(W_BytesIO.read_w),
-read1 = interp2app(W_BytesIO.read1_w),
+read1 = interp2app(W_BytesIO.read_w),
readline = interp2app(W_BytesIO.readline_w),
readinto = interp2app(W_BytesIO.readinto_w),
+readinto1 = interp2app(W_BytesIO.readinto_w),
write = interp2app(W_BytesIO.write_w),
truncate = interp2app(W_BytesIO.truncate_w),
getbuffer = interp2app(W_BytesIO.getbuffer_w),
diff --git a/pypy/module/_io/test/test_bufferedio.py
b/pypy/module/_io/test/test_bufferedio.py
--- a/pypy/module/_io/test/test_bufferedio.py
+++ b/pypy/module/_io/test/test_bufferedio.py
@@ -152,19 +152,28 @@
def test_readinto(self):
import _io
-a = bytearray(b'x' * 10)
-raw = _io.FileIO(self.tmpfile)
-f = _io.BufferedReader(raw)
-assert f.readinto(a) == 5
-f.seek(0)
-m = memoryview(bytearray(b"hello"))
-assert f.readinto(m) == 5
-exc = raises(TypeError, f.readinto, u"hello")
-assert str(exc.value) == "must be read-write buffer, not str"
-exc = raises(TypeError, f.readinto, memoryview(b"hello"))
-assert str(exc.value) == "must be read-write buffer, not memoryview"
-f.close()
-assert a == b'a\nb\ncx'
+for methodname in ["readinto", "readinto1"]:
+a = bytearray(b'x' * 10)
+raw = _io.FileIO(self.tmpfile)
+f = _io.BufferedReader(raw)
+readinto = getattr(f, methodname)
+assert readinto(a) == 5
+f.seek(0)
+m = memoryview(bytearray(b"hello"))
+assert readinto(m) == 5
+#
+exc = raises(TypeError, readinto, u"hello")
+msg = str(exc.value)
+print(msg)
+assert " read-write b" in msg and msg.endswith(", not str")
+#
+exc = raises(TypeError, readinto, memoryview(b"hello"))
+msg = str(exc.value)
+print(msg)
+assert " read-write b" in msg and msg.endswith(", not memoryview")
+#
+f.close()
+assert a == b'a\nb\ncx'
def test_readinto_buffer_overflow(self):
import _io
diff --git a/pypy/module/_io/test/test_bytesio.py
b/pypy/module/_io/test/test_bytesio.py
--- a/pypy/module/_io/test/test_bytesio.py
+++ b/pypy/module/_io/test/test_bytesio.py
@@ -98,23 +98,31 @@
def test_readinto(self):
import _io
-
-b = _io.BytesIO
[pypy-commit] pypy api_func-refactor: Make PyObject_dealloc a slot_function
Author: Ronan Lamy Branch: api_func-refactor Changeset: r89475:4513b1dccd7a Date: 2017-01-10 14:32 + http://bitbucket.org/pypy/pypy/changeset/4513b1dccd7a/ Log:Make PyObject_dealloc a slot_function diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py --- a/pypy/module/cpyext/object.py +++ b/pypy/module/cpyext/object.py @@ -1,7 +1,7 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP, -PyVarObject, Py_buffer, size_t, +PyVarObject, Py_buffer, size_t, slot_function, Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE, CONST_STRING, CONST_STRINGP, FILEP, fwrite) from pypy.module.cpyext.pyobject import ( @@ -54,7 +54,7 @@ w_obj = PyObject_InitVar(space, py_objvar, type, itemcount) return py_obj -@cpython_api([PyObject], lltype.Void) +@slot_function([PyObject], lltype.Void) def PyObject_dealloc(space, obj): return _dealloc(space, obj) @@ -511,7 +511,7 @@ @cpython_api([lltype.Ptr(Py_buffer)], lltype.Void, error=CANNOT_FAIL) def PyBuffer_Release(space, view): """ -Release the buffer view. This should be called when the buffer is +Release the buffer view. This should be called when the buffer is no longer being used as it may free memory from it """ Py_DecRef(space, view.c_obj) ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy api_func-refactor: hg merge default
Author: Ronan Lamy
Branch: api_func-refactor
Changeset: r89474:920775a12e2c
Date: 2017-01-10 13:30 +
http://bitbucket.org/pypy/pypy/changeset/920775a12e2c/
Log:hg merge default
diff too long, truncating to 2000 out of 70624 lines
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -91,3 +91,8 @@
.. branch: cpyext-cleanup
Refactor cpyext initialisation.
+
+.. branch: cpyext-from2
+
+Fix a test failure introduced by strbuf-as-buffer
+
diff --git a/pypy/module/cpyext/memoryobject.py
b/pypy/module/cpyext/memoryobject.py
--- a/pypy/module/cpyext/memoryobject.py
+++ b/pypy/module/cpyext/memoryobject.py
@@ -35,8 +35,24 @@
"""
Fills a newly allocated PyMemoryViewObject with the given W_MemoryView
object.
"""
+assert isinstance(w_obj, W_MemoryView)
py_obj = rffi.cast(PyMemoryViewObject, py_obj)
-py_obj.c_view.c_obj = rffi.cast(PyObject, 0)
+view = py_obj.c_view
+ndim = w_obj.buf.getndim()
+if ndim >= Py_MAX_NDIMS:
+# XXX warn?
+return
+fill_Py_buffer(space, w_obj.buf, view)
+try:
+view.c_buf = rffi.cast(rffi.VOIDP, w_obj.buf.get_raw_address())
+view.c_obj = make_ref(space, w_userdata)
+rffi.setintfield(view, 'c_readonly', w_obj.buf.readonly)
+except ValueError:
+w_s = w_obj.descr_tobytes(space)
+view.c_obj = make_ref(space, w_s)
+view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(space.str_w(w_s),
+ track_allocation=False))
+rffi.setintfield(view, 'c_readonly', 1)
def memory_realize(space, py_obj):
"""
@@ -88,29 +104,13 @@
return ret
@cpython_api([PyObject], Py_bufferP, error=CANNOT_FAIL)
-def PyMemoryView_GET_BUFFER(space, w_obj):
+def PyMemoryView_GET_BUFFER(space, pyobj):
"""Return a pointer to the buffer-info structure wrapped by the given
object. The object must be a memoryview instance; this macro doesn't
check its type, you must do it yourself or you will risk crashes."""
-if not isinstance(w_obj, W_MemoryView):
-return lltype.nullptr(Py_buffer)
-py_memobj = rffi.cast(PyMemoryViewObject, as_pyobj(space, w_obj)) # no
inc_ref
-view = py_memobj.c_view
-ndim = w_obj.buf.getndim()
-if ndim >= Py_MAX_NDIMS:
-# XXX warn?
-return view
-fill_Py_buffer(space, w_obj.buf, view)
-try:
-view.c_buf = rffi.cast(rffi.VOIDP, w_obj.buf.get_raw_address())
-#view.c_obj = make_ref(space, w_obj) # NO - this creates a ref cycle!
-rffi.setintfield(view, 'c_readonly', w_obj.buf.readonly)
-except ValueError:
-w_s = w_obj.descr_tobytes(space)
-view.c_obj = make_ref(space, w_s)
-view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(space.str_w(w_s),
track_allocation=False))
-rffi.setintfield(view, 'c_readonly', 1)
-return view
+# XXX move to a c-macro
+py_memobj = rffi.cast(PyMemoryViewObject, pyobj)
+return py_memobj.c_view
def fill_Py_buffer(space, buf, view):
# c_buf, c_obj have been filled in
@@ -202,9 +202,11 @@
return (_IsCContiguous(view) or _IsFortranContiguous(view))
return 0
-@cpython_api([PyObject], PyObject)
+@cpython_api([PyObject], PyObject, result_is_ll=True)
def PyMemoryView_FromObject(space, w_obj):
-return space.call_method(space.builtin, "memoryview", w_obj)
+w_memview = space.call_method(space.builtin, "memoryview", w_obj)
+py_memview = make_ref(space, w_memview, w_obj)
+return py_memview
@cpython_api([Py_bufferP], PyObject)
def PyMemoryView_FromBuffer(space, view):
@@ -212,6 +214,7 @@
The memoryview object then owns the buffer, which means you shouldn't
try to release it yourself: it will be released on deallocation of the
memoryview object."""
+assert view.c_obj
w_obj = from_ref(space, view.c_obj)
if isinstance(w_obj, W_MemoryView):
return w_obj
diff --git a/pypy/module/cpyext/test/test_memoryobject.py
b/pypy/module/cpyext/test/test_memoryobject.py
--- a/pypy/module/cpyext/test/test_memoryobject.py
+++ b/pypy/module/cpyext/test/test_memoryobject.py
@@ -4,6 +4,7 @@
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from rpython.rlib.buffer import StringBuffer
+from pypy.module.cpyext.pyobject import from_ref
only_pypy ="config.option.runappdirect and '__pypy__' not in
sys.builtin_module_names"
@@ -11,7 +12,7 @@
def test_fromobject(self, space, api):
w_hello = space.newbytes("hello")
assert api.PyObject_CheckBuffer(w_hello)
-w_view = api.PyMemoryView_FromObject(w_hello)
+w_view = from_ref(space, api.PyMemoryView_FromObject(w_hello))
w_char = space.call_method(w_view, '__getitem__', space.wrap(0))
assert space.eq_w(w_char, space.wrap('h'))
w_bytes = space.call
[pypy-commit] pypy py3.5: Tweak: W_IOBase is the only class in CPython 3.5 to have both a
Author: Armin Rigo
Branch: py3.5
Changeset: r89476:3e79e13a6a69
Date: 2017-01-10 17:53 +0100
http://bitbucket.org/pypy/pypy/changeset/3e79e13a6a69/
Log:Tweak: W_IOBase is the only class in CPython 3.5 to have both a
tp_finalize and be overridable. This gives semantics that are
markedly different from the old (<= 3.3) ones, and that are closer
to app-level classes. See comments
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -13,7 +13,7 @@
class TypeDef(object):
def __init__(self, __name, __base=None, __total_ordering__=None,
- __buffer=None, **rawdict):
+ __buffer=None, __confirm_applevel_del__=False, **rawdict):
"NOT_RPYTHON: initialization-time only"
self.name = __name
if __base is None:
@@ -29,7 +29,8 @@
self.heaptype = False
self.hasdict = '__dict__' in rawdict
# no __del__: use an RPython _finalize_() method and register_finalizer
-assert '__del__' not in rawdict
+if not __confirm_applevel_del__:
+assert '__del__' not in rawdict
self.weakrefable = '__weakref__' in rawdict
self.doc = rawdict.get('__doc__', None)
for base in bases:
diff --git a/pypy/module/_io/interp_bufferedio.py
b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -1010,16 +1010,6 @@
self.w_writer = None
raise
-def _finalize_(self):
-# Don't call the base __del__: do not close the files!
-# Usually the _finalize_() method is not called at all because
-# we set 'needs_to_finalize = False' in this class, so
-# W_IOBase.__init__() won't call register_finalizer().
-# However, this method might still be called: if the user
-# makes an app-level subclass and adds a custom __del__.
-pass
-needs_to_finalize = False
-
# forward to reader
for method in ['read', 'peek', 'read1', 'readinto', 'readable']:
locals()[method + '_w'] = make_forwarding_method(
@@ -1052,6 +1042,10 @@
if e:
raise e
+def needs_finalizer(self):
+# self.w_writer and self.w_reader have their own finalizer
+return type(self) is not W_BufferedRWPair
+
def isatty_w(self, space):
if space.is_true(space.call_method(self.w_writer, "isatty")):
return space.w_True
diff --git a/pypy/module/_io/interp_bytesio.py
b/pypy/module/_io/interp_bytesio.py
--- a/pypy/module/_io/interp_bytesio.py
+++ b/pypy/module/_io/interp_bytesio.py
@@ -166,6 +166,10 @@
def close_w(self, space):
self.close()
+def needs_finalizer(self):
+# self.close() is not necessary when the object goes away
+return type(self) is not W_BytesIO
+
def closed_get_w(self, space):
return space.wrap(self.is_closed())
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -60,7 +60,7 @@
self.__IOBase_closed = False
if add_to_autoflusher:
get_autoflusher(space).add(self)
-if self.needs_to_finalize:
+if self.needs_finalizer():
self.register_finalizer(space)
def getdict(self, space):
@@ -75,6 +75,18 @@
return False
def _finalize_(self):
+# Note: there is only this empty _finalize_() method here, but
+# we still need register_finalizer() so that descr_del() is
+# called. IMPORTANT: this is not the recommended way to have a
+# finalizer! It makes the finalizer appear as __del__() from
+# app-level, and the user can call __del__() explicitly, or
+# override it, with or without calling the parent's __del__().
+# This matches 'tp_finalize' in CPython >= 3.4. So far (3.5),
+# this is the only built-in class with a 'tp_finalize' slot that
+# can be subclassed.
+pass
+
+def descr_del(self):
space = self.space
w_closed = space.findattr(self, space.wrap('closed'))
try:
@@ -90,7 +102,6 @@
# equally as bad, and potentially more frequent (because of
# shutdown issues).
pass
-needs_to_finalize = True
def _CLOSED(self):
# Use this macro whenever you want to check the internal `closed`
@@ -128,6 +139,11 @@
finally:
self.__IOBase_closed = True
+def needs_finalizer(self):
+# can return False if we know that the precise close() method
+# of this class will have no effect
+return True
+
def _dealloc_warn_w(self, space, w_source):
"""Called when the io is implicitly closed via the deconstructor"""
pass
@@ -318,6 +334,8 @@
[pypy-commit] pypy api_func-refactor: Close branch api_func-refactor
Author: Ronan Lamy Branch: api_func-refactor Changeset: r89477:b7e9f3538e0e Date: 2017-01-10 18:46 + http://bitbucket.org/pypy/pypy/changeset/b7e9f3538e0e/ Log:Close branch api_func-refactor ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Merged in api_func-refactor (pull request #505)
Author: Ronan Lamy
Branch:
Changeset: r89478:11109e66a206
Date: 2017-01-10 18:46 +
http://bitbucket.org/pypy/pypy/changeset/11109e66a206/
Log:Merged in api_func-refactor (pull request #505)
Refactor ApiFunction
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -329,66 +329,19 @@
wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
return wrapper
-DEFAULT_HEADER = 'pypy_decl.h'
-def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, header=DEFAULT_HEADER,
-gil=None, result_borrowed=False, result_is_ll=False):
-"""
-Declares a function to be exported.
-- `argtypes`, `restype` are lltypes and describe the function signature.
-- `error` is the value returned when an applevel exception is raised. The
- special value 'CANNOT_FAIL' (also when restype is Void) turns an eventual
- exception into a wrapped SystemError. Unwrapped exceptions also cause a
- SytemError.
-- `header` is the header file to export the function in, Set to None to get
- a C function pointer, but not exported by the API headers.
-- set `gil` to "acquire", "release" or "around" to acquire the GIL,
- release the GIL, or both
-"""
-if isinstance(restype, lltype.Typedef):
-real_restype = restype.OF
-else:
-real_restype = restype
-
-if error is _NOT_SPECIFIED:
-if isinstance(real_restype, lltype.Ptr):
-error = lltype.nullptr(real_restype.TO)
-elif real_restype is lltype.Void:
-error = CANNOT_FAIL
-if type(error) is int:
-error = rffi.cast(real_restype, error)
-expect_integer = (isinstance(real_restype, lltype.Primitive) and
- rffi.cast(restype, 0) == 0)
-
-def decorate(func):
-func._always_inline_ = 'try'
-func_name = func.func_name
-if header is not None:
-c_name = None
-if func_name in FUNCTIONS_BY_HEADER[header]:
-raise ValueError("%s already registered" % func_name)
-else:
-c_name = func_name
-api_function = ApiFunction(argtypes, restype, func, error,
- c_name=c_name, gil=gil,
- result_borrowed=result_borrowed,
- result_is_ll=result_is_ll)
-func.api_func = api_function
-
-if error is _NOT_SPECIFIED:
-raise ValueError("function %s has no return value for exceptions"
- % func)
-names = api_function.argnames
-types_names_enum_ui = unrolling_iterable(enumerate(
-zip(api_function.argtypes,
-[tp_name.startswith("w_") for tp_name in names])))
+def get_unwrapper(self):
+names = self.argnames
+argtypesw = zip(self.argtypes,
+[_name.startswith("w_") for _name in self.argnames])
+types_names_enum_ui = unrolling_iterable(enumerate(argtypesw))
@specialize.ll()
def unwrapper(space, *args):
-from pypy.module.cpyext.pyobject import Py_DecRef, is_pyobj
+from pypy.module.cpyext.pyobject import is_pyobj
from pypy.module.cpyext.pyobject import from_ref, as_pyobj
newargs = ()
keepalives = ()
-assert len(args) == len(api_function.argtypes)
+assert len(args) == len(self.argtypes)
for i, (ARG, is_wrapped) in types_names_enum_ui:
input_arg = args[i]
if is_PyObject(ARG) and not is_wrapped:
@@ -413,31 +366,79 @@
arg = from_ref(space, input_arg)
else:
arg = input_arg
-
-## ZZZ: for is_pyobj:
-## try:
-## arg = from_ref(space,
-##rffi.cast(PyObject, input_arg))
-## except TypeError, e:
-## err = oefmt(space.w_TypeError,
-## "could not cast arg to PyObject")
-## if not catch_exception:
-## raise err
-## state = space.fromcache(State)
-## state.set_exception(err)
-## if is_PyObject(restype):
-## return None
-## else:
-## return api_function.error_value
else:
# arg is not declared as PyObject, no magic
arg = input_arg
newargs += (arg, )
try:
-return func(space, *newargs)
+return self.callable(space, *newargs)
finally:
keepa
[pypy-commit] pypy default: "document" merged branch
Author: Ronan Lamy Branch: Changeset: r89479:745ebe24fc0b Date: 2017-01-10 18:48 + http://bitbucket.org/pypy/pypy/changeset/745ebe24fc0b/ Log:"document" merged branch diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -89,6 +89,7 @@ is readonly) without pinning it. .. branch: cpyext-cleanup +.. branch: api_func-refactor Refactor cpyext initialisation. ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy rffi-parser-2: hg merge default
Author: Ronan Lamy
Branch: rffi-parser-2
Changeset: r89480:0b2f88ee4865
Date: 2017-01-10 19:07 +
http://bitbucket.org/pypy/pypy/changeset/0b2f88ee4865/
Log:hg merge default
diff too long, truncating to 2000 out of 71624 lines
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -89,5 +89,11 @@
is readonly) without pinning it.
.. branch: cpyext-cleanup
+.. branch: api_func-refactor
Refactor cpyext initialisation.
+
+.. branch: cpyext-from2
+
+Fix a test failure introduced by strbuf-as-buffer
+
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -323,66 +323,19 @@
wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
return wrapper
-DEFAULT_HEADER = 'pypy_decl.h'
-def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, header=DEFAULT_HEADER,
-gil=None, result_borrowed=False, result_is_ll=False):
-"""
-Declares a function to be exported.
-- `argtypes`, `restype` are lltypes and describe the function signature.
-- `error` is the value returned when an applevel exception is raised. The
- special value 'CANNOT_FAIL' (also when restype is Void) turns an eventual
- exception into a wrapped SystemError. Unwrapped exceptions also cause a
- SytemError.
-- `header` is the header file to export the function in, Set to None to get
- a C function pointer, but not exported by the API headers.
-- set `gil` to "acquire", "release" or "around" to acquire the GIL,
- release the GIL, or both
-"""
-if isinstance(restype, lltype.Typedef):
-real_restype = restype.OF
-else:
-real_restype = restype
-
-if error is _NOT_SPECIFIED:
-if isinstance(real_restype, lltype.Ptr):
-error = lltype.nullptr(real_restype.TO)
-elif real_restype is lltype.Void:
-error = CANNOT_FAIL
-if type(error) is int:
-error = rffi.cast(real_restype, error)
-expect_integer = (isinstance(real_restype, lltype.Primitive) and
- rffi.cast(restype, 0) == 0)
-
-def decorate(func):
-func._always_inline_ = 'try'
-func_name = func.func_name
-if header is not None:
-c_name = None
-if func_name in FUNCTIONS_BY_HEADER[header]:
-raise ValueError("%s already registered" % func_name)
-else:
-c_name = func_name
-api_function = ApiFunction(argtypes, restype, func, error,
- c_name=c_name, gil=gil,
- result_borrowed=result_borrowed,
- result_is_ll=result_is_ll)
-func.api_func = api_function
-
-if error is _NOT_SPECIFIED:
-raise ValueError("function %s has no return value for exceptions"
- % func)
-names = api_function.argnames
-types_names_enum_ui = unrolling_iterable(enumerate(
-zip(api_function.argtypes,
-[tp_name.startswith("w_") for tp_name in names])))
+def get_unwrapper(self):
+names = self.argnames
+argtypesw = zip(self.argtypes,
+[_name.startswith("w_") for _name in self.argnames])
+types_names_enum_ui = unrolling_iterable(enumerate(argtypesw))
@specialize.ll()
def unwrapper(space, *args):
-from pypy.module.cpyext.pyobject import Py_DecRef, is_pyobj
+from pypy.module.cpyext.pyobject import is_pyobj
from pypy.module.cpyext.pyobject import from_ref, as_pyobj
newargs = ()
keepalives = ()
-assert len(args) == len(api_function.argtypes)
+assert len(args) == len(self.argtypes)
for i, (ARG, is_wrapped) in types_names_enum_ui:
input_arg = args[i]
if is_PyObject(ARG) and not is_wrapped:
@@ -407,31 +360,79 @@
arg = from_ref(space, input_arg)
else:
arg = input_arg
-
-## ZZZ: for is_pyobj:
-## try:
-## arg = from_ref(space,
-##rffi.cast(PyObject, input_arg))
-## except TypeError, e:
-## err = oefmt(space.w_TypeError,
-## "could not cast arg to PyObject")
-## if not catch_exception:
-## raise err
-## state = space.fromcache(State)
-## state.set_exception(err)
-## if is_PyObject(restype):
-## return None
-## else:
-
[pypy-commit] pypy rffi-parser-2: Parse function declarations
Author: Ronan Lamy
Branch: rffi-parser-2
Changeset: r89481:5ce867e5a994
Date: 2017-01-10 19:46 +
http://bitbucket.org/pypy/pypy/changeset/5ce867e5a994/
Log:Parse function declarations
diff --git a/pypy/module/cpyext/cparser.py b/pypy/module/cpyext/cparser.py
--- a/pypy/module/cpyext/cparser.py
+++ b/pypy/module/cpyext/cparser.py
@@ -783,6 +783,16 @@
result = result.TYPE
return result
+def parse_func(self, cdecl):
+cdecl = cdecl.strip()
+if cdecl[-1] != ';':
+cdecl += ';'
+ast, _, _ = self.ctx._parse(cdecl)
+decl = ast.ext[-1]
+tp, quals = self.ctx._get_type_and_quals(decl.type, name=decl.name)
+FUNCP = self.convert_type(tp.as_function_pointer())
+return decl.name, FUNCP.TO
+
def parse_source(source, includes=None, eci=None, configure_now=False):
ctx = Parser()
diff --git a/pypy/module/cpyext/test/test_cparser.py
b/pypy/module/cpyext/test/test_cparser.py
--- a/pypy/module/cpyext/test/test_cparser.py
+++ b/pypy/module/cpyext/test/test_cparser.py
@@ -163,3 +163,28 @@
res = parse_source(decl, eci=eci, configure_now=True)
assert res.gettype('Py_ssize_t') == rffi.SSIZE_T
assert res.gettype('TestFloatObject *').TO.c_ob_refcnt == rffi.SSIZE_T
+
+def test_parse_funcdecl(tmpdir):
+decl = """
+typedef ssize_t Py_ssize_t;
+
+#define PyObject_HEAD \
+Py_ssize_t ob_refcnt;\
+Py_ssize_t ob_pypy_link; \
+
+typedef struct {
+PyObject_HEAD
+double ob_fval;
+} TestFloatObject;
+
+typedef TestFloatObject* (*func_t)(int, int);
+"""
+hdr = tmpdir / 'header.h'
+hdr.write(decl)
+eci = ExternalCompilationInfo(
+include_dirs=[str(tmpdir)], includes=['sys/types.h', 'header.h'])
+res = parse_source(decl, eci=eci, configure_now=True)
+name, FUNC = res.parse_func("func_t some_func(TestFloatObject*)")
+assert name == 'some_func'
+assert FUNC.RESULT == res.gettype('func_t')
+assert FUNC.ARGS == (res.gettype('TestFloatObject *'),)
___
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy cpyext-FromBuffer: fix translation (ndim, readonly need widen() )
Author: Matti Picus Branch: cpyext-FromBuffer Changeset: r89482:629285e34cf7 Date: 2017-01-10 22:51 +0200 http://bitbucket.org/pypy/pypy/changeset/629285e34cf7/ Log:fix translation (ndim, readonly need widen() ) diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py --- a/pypy/module/cpyext/memoryobject.py +++ b/pypy/module/cpyext/memoryobject.py @@ -61,19 +61,20 @@ from pypy.module.cpyext.slotdefs import CPyBuffer, fq py_mem = rffi.cast(PyMemoryViewObject, obj) view = py_mem.c_view +ndim = widen(view.c_ndim) shape = None if view.c_shape: -shape = [view.c_shape[i] for i in range(view.c_ndim)] +shape = [view.c_shape[i] for i in range(ndim)] strides = None if view.c_strides: -strides = [view.c_strides[i] for i in range(view.c_ndim)] +strides = [view.c_strides[i] for i in range(ndim)] format = 'B' if view.c_format: format = rffi.charp2str(view.c_format) buf = CPyBuffer(space, view.c_buf, view.c_len, from_ref(space, view.c_obj), format=format, shape=shape, strides=strides, -ndim=view.c_ndim, itemsize=view.c_itemsize, -readonly=view.c_readonly) +ndim=ndim, itemsize=view.c_itemsize, +readonly=widen(view.c_readonly)) # Ensure view.c_buf is released upon object finalization fq.register_finalizer(buf) # Allow subclassing W_MemeoryView ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: merge cpyext-FromBuffer which fixes ref leak in PyMemoryView_FromBuffer
Author: Matti Picus Branch: Changeset: r89484:28d4f9418183 Date: 2017-01-10 23:40 +0200 http://bitbucket.org/pypy/pypy/changeset/28d4f9418183/ Log:merge cpyext-FromBuffer which fixes ref leak in PyMemoryView_FromBuffer diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -124,6 +124,7 @@ METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O Py_TPFLAGS_HAVE_INPLACEOPS Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_HAVE_NEWBUFFER Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES Py_MAX_NDIMS +PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES """.split() for name in constant_names: setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name)) diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py --- a/pypy/module/cpyext/memoryobject.py +++ b/pypy/module/cpyext/memoryobject.py @@ -3,7 +3,8 @@ build_type_checkers, Py_ssize_tP, PyObjectFields, cpython_struct, bootstrap_function, Py_bufferP, slot_function) from pypy.module.cpyext.pyobject import ( -PyObject, make_ref, as_pyobj, incref, decref, from_ref, make_typedescr) +PyObject, make_ref, as_pyobj, incref, decref, from_ref, make_typedescr, +get_typedescr, track_reference) from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib.rarithmetic import widen from pypy.objspace.std.memoryobject import W_MemoryView @@ -28,7 +29,7 @@ basestruct=PyMemoryViewObject.TO, attach=memory_attach, dealloc=memory_dealloc, - #realize=memory_realize, + realize=memory_realize, ) def memory_attach(space, py_obj, w_obj, w_userdata=None): @@ -54,11 +55,35 @@ track_allocation=False)) rffi.setintfield(view, 'c_readonly', 1) -def memory_realize(space, py_obj): +def memory_realize(space, obj): """ Creates the memory object in the interpreter """ -raise oefmt(space.w_NotImplementedError, "cannot call this yet") +from pypy.module.cpyext.slotdefs import CPyBuffer, fq +py_mem = rffi.cast(PyMemoryViewObject, obj) +view = py_mem.c_view +ndim = widen(view.c_ndim) +shape = None +if view.c_shape: +shape = [view.c_shape[i] for i in range(ndim)] +strides = None +if view.c_strides: +strides = [view.c_strides[i] for i in range(ndim)] +format = 'B' +if view.c_format: +format = rffi.charp2str(view.c_format) +buf = CPyBuffer(space, view.c_buf, view.c_len, from_ref(space, view.c_obj), +format=format, shape=shape, strides=strides, +ndim=ndim, itemsize=view.c_itemsize, +readonly=widen(view.c_readonly)) +# Ensure view.c_buf is released upon object finalization +fq.register_finalizer(buf) +# Allow subclassing W_MemeoryView +w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) +w_obj = space.allocate_instance(W_MemoryView, w_type) +w_obj.__init__(buf) +track_reference(space, obj, w_obj) +return w_obj @slot_function([PyObject], lltype.Void) def memory_dealloc(space, py_obj): @@ -208,17 +233,41 @@ py_memview = make_ref(space, w_memview, w_obj) return py_memview -@cpython_api([Py_bufferP], PyObject) +@cpython_api([Py_bufferP], PyObject, result_is_ll=True) def PyMemoryView_FromBuffer(space, view): """Create a memoryview object wrapping the given buffer-info structure view. The memoryview object then owns the buffer, which means you shouldn't try to release it yourself: it will be released on deallocation of the memoryview object.""" -assert view.c_obj -w_obj = from_ref(space, view.c_obj) -if isinstance(w_obj, W_MemoryView): -return w_obj -return space.call_method(space.builtin, "memoryview", w_obj) +# XXX this should allocate a PyMemoryViewObject and +# copy view into obj.c_view, without creating a new view.c_obj +typedescr = get_typedescr(W_MemoryView.typedef) +py_obj = typedescr.allocate(space, space.w_memoryview) +py_mem = rffi.cast(PyMemoryViewObject, py_obj) +mview = py_mem.c_view +mview.c_buf = view.c_buf +mview.c_obj = view.c_obj +mview.c_len = view.c_len +mview.c_itemsize = view.c_itemsize +mview.c_readonly = view.c_readonly +mview.c_ndim = view.c_ndim +mview.c_format = view.c_format +if view.c_strides == rffi.cast(Py_ssize_tP, view.c__strides): +py_mem.c_view.c_strides = rffi.cast(Py_ssize_tP, py_mem.c_view.c__strides) +for i in range(view.c_ndim): +py_mem.c_view.c_strides[i] = view.c_strides[i] +else: +# some externally allocated memory chunk +py_mem.c_view.c_strides = view.c_strides +if view.c_shape == rffi.cast(Py_ssize_tP, view.c__shape): +py_mem.c_view.c_shape = rffi.cast(Py_ssize_tP, py_mem.c_vi
[pypy-commit] pypy missing-tp_new: cpython_api ... header=None => slot_function
Author: Matti Picus
Branch: missing-tp_new
Changeset: r89487:748bf3d6f4c5
Date: 2017-01-11 00:37 +0200
http://bitbucket.org/pypy/pypy/changeset/748bf3d6f4c5/
Log:cpython_api ... header=None => slot_function
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -562,7 +562,7 @@
slot_fn = w_type.getdictvalue(space, attr)
if slot_fn is None:
return
-@cpython_api([PyObject], lltype.Signed, header=header, error=-1)
+@slot_function([PyObject], lltype.Signed, header=header, error=-1)
@func_renamer("cpyext_%s_%s" % (name.replace('.', '_'),
typedef.name))
def slot_func(space, w_obj):
return space.int_w(space.call_function(slot_fn, w_obj))
diff --git a/pypy/module/cpyext/userslot.py b/pypy/module/cpyext/userslot.py
--- a/pypy/module/cpyext/userslot.py
+++ b/pypy/module/cpyext/userslot.py
@@ -12,23 +12,23 @@
from pypy.interpreter.error import oefmt
from pypy.interpreter.argument import Arguments
-from pypy.module.cpyext.api import cpython_api, PyObject, Py_ssize_t
+from pypy.module.cpyext.api import slot_function, PyObject, Py_ssize_t
from pypy.module.cpyext.api import PyTypeObjectPtr
from rpython.rtyper.lltypesystem import rffi, lltype
-@cpython_api([PyObject], Py_ssize_t, error=-1, header=None)
+@slot_function([PyObject], Py_ssize_t, error=-1)
def slot_sq_length(space, w_obj):
return space.int_w(space.len(w_obj))
-@cpython_api([PyObject], lltype.Signed, header=None, error=-1)
+@slot_function([PyObject], lltype.Signed, error=-1)
def slot_tp_hash(space, w_obj):
return space.int_w(space.hash(w_obj))
-@cpython_api([PyObject, Py_ssize_t], PyObject, header=None)
+@slot_function([PyObject, Py_ssize_t], PyObject)
def slot_sq_item(space, w_obj, index):
return space.getitem(w_obj, space.wrap(index))
-@cpython_api([PyTypeObjectPtr, PyObject, PyObject], PyObject, header=None)
+@slot_function([PyTypeObjectPtr, PyObject, PyObject], PyObject)
def slot_tp_new(space, w_type, w_args, w_kwds):
# XXX problem - we need to find the actual __new__ function to call.
# but we have no 'self' argument. Theoretically, self will be
@@ -51,61 +51,61 @@
# unary functions
-@cpython_api([PyObject], PyObject, header=None)
+@slot_function([PyObject], PyObject)
def slot_tp_str(space, w_obj):
return space.str(w_obj)
-@cpython_api([PyObject], PyObject, header=None)
+@slot_function([PyObject], PyObject)
def slot_tp_repr(space, w_obj):
return space.repr(w_obj)
#binary functions
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_nb_add(space, w_obj1, w_obj2):
return space.add(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_nb_subtract(space, w_obj1, w_obj2):
return space.sub(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_nb_multiply(space, w_obj1, w_obj2):
return space.mul(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_nb_divide(space, w_obj1, w_obj2):
return space.div(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_nb_inplace_add(space, w_obj1, w_obj2):
return space.add(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_nb_inplace_subtract(space, w_obj1, w_obj2):
return space.sub(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_nb_inplace_multiply(space, w_obj1, w_obj2):
return space.mul(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_nb_inplace_divide(space, w_obj1, w_obj2):
return space.div(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_sq_concat(space, w_obj1, w_obj2):
return space.add(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_sq_inplace_concat(space, w_obj1, w_obj2):
return space.add(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_mp_subscript(space, w_obj1, w_obj2):
return space.getitem(w_obj1, w_obj2)
-@cpython_api([PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject], PyObject)
def slot_tp_getattr(space, w_obj1, w_obj2):
return space.getattr(w_obj1, w_
[pypy-commit] pypy cpyext-FromBuffer: close branch to be merged
Author: Matti Picus Branch: cpyext-FromBuffer Changeset: r89483:483f0ddb128f Date: 2017-01-10 23:37 +0200 http://bitbucket.org/pypy/pypy/changeset/483f0ddb128f/ Log:close branch to be merged ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: document merged branch
Author: Matti Picus Branch: Changeset: r89485:9bfc055b22fc Date: 2017-01-10 23:44 +0200 http://bitbucket.org/pypy/pypy/changeset/9bfc055b22fc/ Log:document merged branch diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -97,3 +97,7 @@ Fix a test failure introduced by strbuf-as-buffer +.. branch: cpyext-FromBuffer + +Do not recreate the object in PyMemoryView_FromBuffer, rather pass it to +the returned PyMemoryViewObject, to take ownership of it. Fixes a ref leak. ___ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy missing-tp_new: merge default into branch
Author: Matti Picus
Branch: missing-tp_new
Changeset: r89486:99f094da36b2
Date: 2017-01-10 23:45 +0200
http://bitbucket.org/pypy/pypy/changeset/99f094da36b2/
Log:merge default into branch
diff too long, truncating to 2000 out of 71830 lines
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -89,5 +89,15 @@
is readonly) without pinning it.
.. branch: cpyext-cleanup
+.. branch: api_func-refactor
Refactor cpyext initialisation.
+
+.. branch: cpyext-from2
+
+Fix a test failure introduced by strbuf-as-buffer
+
+.. branch: cpyext-FromBuffer
+
+Do not recreate the object in PyMemoryView_FromBuffer, rather pass it to
+the returned PyMemoryViewObject, to take ownership of it. Fixes a ref leak.
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -125,6 +125,7 @@
METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O Py_TPFLAGS_HAVE_INPLACEOPS
Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_HAVE_NEWBUFFER
Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES Py_MAX_NDIMS
+PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES
""".split()
for name in constant_names:
setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name))
@@ -330,66 +331,19 @@
wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
return wrapper
-DEFAULT_HEADER = 'pypy_decl.h'
-def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, header=DEFAULT_HEADER,
-gil=None, result_borrowed=False, result_is_ll=False):
-"""
-Declares a function to be exported.
-- `argtypes`, `restype` are lltypes and describe the function signature.
-- `error` is the value returned when an applevel exception is raised. The
- special value 'CANNOT_FAIL' (also when restype is Void) turns an eventual
- exception into a wrapped SystemError. Unwrapped exceptions also cause a
- SytemError.
-- `header` is the header file to export the function in, Set to None to get
- a C function pointer, but not exported by the API headers.
-- set `gil` to "acquire", "release" or "around" to acquire the GIL,
- release the GIL, or both
-"""
-if isinstance(restype, lltype.Typedef):
-real_restype = restype.OF
-else:
-real_restype = restype
-
-if error is _NOT_SPECIFIED:
-if isinstance(real_restype, lltype.Ptr):
-error = lltype.nullptr(real_restype.TO)
-elif real_restype is lltype.Void:
-error = CANNOT_FAIL
-if type(error) is int:
-error = rffi.cast(real_restype, error)
-expect_integer = (isinstance(real_restype, lltype.Primitive) and
- rffi.cast(restype, 0) == 0)
-
-def decorate(func):
-func._always_inline_ = 'try'
-func_name = func.func_name
-if header is not None:
-c_name = None
-if func_name in FUNCTIONS_BY_HEADER[header]:
-raise ValueError("%s already registered" % func_name)
-else:
-c_name = func_name
-api_function = ApiFunction(argtypes, restype, func, error,
- c_name=c_name, gil=gil,
- result_borrowed=result_borrowed,
- result_is_ll=result_is_ll)
-func.api_func = api_function
-
-if error is _NOT_SPECIFIED:
-raise ValueError("function %s has no return value for exceptions"
- % func)
-names = api_function.argnames
-types_names_enum_ui = unrolling_iterable(enumerate(
-zip(api_function.argtypes,
-[tp_name.startswith("w_") for tp_name in names])))
+def get_unwrapper(self):
+names = self.argnames
+argtypesw = zip(self.argtypes,
+[_name.startswith("w_") for _name in self.argnames])
+types_names_enum_ui = unrolling_iterable(enumerate(argtypesw))
@specialize.ll()
def unwrapper(space, *args):
-from pypy.module.cpyext.pyobject import Py_DecRef, is_pyobj
+from pypy.module.cpyext.pyobject import is_pyobj
from pypy.module.cpyext.pyobject import from_ref, as_pyobj
newargs = ()
keepalives = ()
-assert len(args) == len(api_function.argtypes)
+assert len(args) == len(self.argtypes)
for i, (ARG, is_wrapped) in types_names_enum_ui:
input_arg = args[i]
if is_PyObject(ARG) and not is_wrapped:
@@ -414,31 +368,79 @@
arg = from_ref(space, input_arg)
else:
arg = input_arg
-
-## ZZZ: for is_pyobj:
-## try:
-## arg = from_ref(space,
-##rffi.cast(PyObject, input_
[pypy-commit] pypy default: Cleanup; kill _create_api_func()
Author: Ronan Lamy
Branch:
Changeset: r89488:c501282f4438
Date: 2017-01-11 03:15 +
http://bitbucket.org/pypy/pypy/changeset/c501282f4438/
Log:Cleanup; kill _create_api_func()
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -249,14 +249,13 @@
cpyext_namespace = NameManager('cpyext_')
class ApiFunction(object):
-def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED,
+def __init__(self, argtypes, restype, callable, error=CANNOT_FAIL,
c_name=None, gil=None, result_borrowed=False,
result_is_ll=False):
self.argtypes = argtypes
self.restype = restype
self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype))
self.callable = callable
-if error is not _NOT_SPECIFIED:
-self.error_value = error
+self.error_value = error
self.c_name = c_name
# extract the signature from the (CPython-level) code object
@@ -298,7 +297,7 @@
argtypesw = zip(self.argtypes,
[_name.startswith("w_") for _name in self.argnames])
-error_value = getattr(self, "error_value", CANNOT_FAIL)
+error_value = self.error_value
if (isinstance(self.restype, lltype.Ptr)
and error_value is not CANNOT_FAIL):
assert lltype.typeOf(error_value) == self.restype
@@ -436,12 +435,12 @@
def decorate(func):
if func.__name__ in FUNCTIONS_BY_HEADER[header]:
raise ValueError("%s already registered" % func.__name__)
-api_function = _create_api_func(
-func, argtypes, restype, error, gil=gil,
+func._always_inline_ = 'try'
+api_function = ApiFunction(
+argtypes, restype, func,
+error=_compute_error(error, restype), gil=gil,
result_borrowed=result_borrowed, result_is_ll=result_is_ll)
-unwrapper = api_function.get_unwrapper()
-unwrapper.func = func
-unwrapper.api_func = api_function
+FUNCTIONS_BY_HEADER[header][func.__name__] = api_function
# ZZZ is this whole logic really needed??? It seems to be only
# for RPython code calling PyXxx() functions directly. I would
@@ -469,32 +468,33 @@
assert got_integer == expect_integer, (
'got %r not integer' % (res,))
return res
+INTERPLEVEL_API[func.__name__] = unwrapper_catch # used in tests
-if header is not None:
-FUNCTIONS_BY_HEADER[header][func.__name__] = api_function
-INTERPLEVEL_API[func.__name__] = unwrapper_catch # used in tests
-return unwrapper
-return decorate
-
-def slot_function(argtypes, restype, error=_NOT_SPECIFIED):
-def decorate(func):
-c_name = func.__name__
-api_function = _create_api_func(func, argtypes, restype, error, c_name)
unwrapper = api_function.get_unwrapper()
unwrapper.func = func
unwrapper.api_func = api_function
return unwrapper
return decorate
+def slot_function(argtypes, restype, error=_NOT_SPECIFIED):
+def decorate(func):
+func._always_inline_ = 'try'
+api_function = ApiFunction(
+argtypes, restype, func,
+error=_compute_error(error, restype),
+c_name=func.__name__)
+unwrapper = api_function.get_unwrapper()
+unwrapper.func = func
+unwrapper.api_func = api_function
+return unwrapper
+return decorate
-def _create_api_func(
-func, argtypes, restype, error=_NOT_SPECIFIED, c_name=None,
-gil=None, result_borrowed=False, result_is_ll=False):
+def _compute_error(error, restype):
+"""Convert error specification to actual error value of type restype."""
if isinstance(restype, lltype.Typedef):
real_restype = restype.OF
else:
real_restype = restype
-
if error is _NOT_SPECIFIED:
if isinstance(real_restype, lltype.Ptr):
error = lltype.nullptr(real_restype.TO)
@@ -502,11 +502,7 @@
error = CANNOT_FAIL
if type(error) is int:
error = rffi.cast(real_restype, error)
-
-func._always_inline_ = 'try'
-return ApiFunction(
-argtypes, restype, func, error, c_name=c_name, gil=gil,
-result_borrowed=result_borrowed, result_is_ll=result_is_ll)
+return error
def cpython_struct(name, fields, forward=None, level=1):
___
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit
