[pypy-commit] pypy py3.5: Detail: CO_GENERATOR is set in addition to CO_COROUTINE in some (nonsensical imho) cases

2017-01-10 Thread arigo
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

2017-01-10 Thread arigo
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

2017-01-10 Thread arigo
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__

2017-01-10 Thread arigo
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

2017-01-10 Thread arigo
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

2017-01-10 Thread arigo
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

2017-01-10 Thread arigo
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

2017-01-10 Thread arigo
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

2017-01-10 Thread arigo
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

2017-01-10 Thread arigo
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

2017-01-10 Thread arigo
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

2017-01-10 Thread arigo
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

2017-01-10 Thread rlamy
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

2017-01-10 Thread rlamy
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

2017-01-10 Thread arigo
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

2017-01-10 Thread rlamy
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)

2017-01-10 Thread rlamy
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

2017-01-10 Thread rlamy
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

2017-01-10 Thread rlamy
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

2017-01-10 Thread rlamy
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() )

2017-01-10 Thread mattip
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

2017-01-10 Thread mattip
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

2017-01-10 Thread mattip
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

2017-01-10 Thread mattip
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

2017-01-10 Thread mattip
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

2017-01-10 Thread mattip
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()

2017-01-10 Thread rlamy
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