[pypy-commit] pypy py3.5: hg merge default
arigo
pypy.commits at gmail.com
Tue Jan 17 12:03:53 EST 2017
Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r89636:6d7e97a686d7
Date: 2017-01-17 18:03 +0100
http://bitbucket.org/pypy/pypy/changeset/6d7e97a686d7/
Log: hg merge default
diff too long, truncating to 2000 out of 3163 lines
diff --git a/lib-python/2.7/sqlite3/test/regression.py b/lib-python/2.7/sqlite3/test/regression.py
--- a/lib-python/2.7/sqlite3/test/regression.py
+++ b/lib-python/2.7/sqlite3/test/regression.py
@@ -351,10 +351,7 @@
self.assertRaises(ValueError, cur.execute, " \0select 2")
self.assertRaises(ValueError, cur.execute, "select 2\0")
- @test_support.impl_detail(pypy=False)
def CheckCommitCursorReset(self):
- # This test is for logic added in 2.7.13 which PyPy doesn't
- # implement. See http://bugs.python.org/issue29006
"""
Connection.commit() did reset cursors, which made sqlite3
to return rows multiple times when fetched from cursors
diff --git a/lib-python/2.7/test/test_capi.py b/lib-python/2.7/test/test_capi.py
--- a/lib-python/2.7/test/test_capi.py
+++ b/lib-python/2.7/test/test_capi.py
@@ -26,7 +26,6 @@
skips = []
if support.check_impl_detail(pypy=True):
skips += [
- 'test_broken_memoryview',
'test_buildvalue_N',
'test_capsule',
'test_lazy_hash_inheritance',
diff --git a/lib-python/2.7/test/test_multiprocessing.py b/lib-python/2.7/test/test_multiprocessing.py
--- a/lib-python/2.7/test/test_multiprocessing.py
+++ b/lib-python/2.7/test/test_multiprocessing.py
@@ -1969,9 +1969,10 @@
if not gc.isenabled():
gc.enable()
self.addCleanup(gc.disable)
- #thresholds = gc.get_threshold()
- #self.addCleanup(gc.set_threshold, *thresholds)
- #gc.set_threshold(10)
+ if test_support.check_impl_detail(cpython=True):
+ thresholds = gc.get_threshold()
+ self.addCleanup(gc.set_threshold, *thresholds)
+ gc.set_threshold(10)
# perform numerous block allocations, with cyclic references to make
# sure objects are collected asynchronously by the gc
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -231,6 +231,7 @@
self.__statements_counter = 0
self.__rawstatements = set()
self._statement_cache = _StatementCache(self, cached_statements)
+ self.__statements_already_committed = []
self.__func_cache = {}
self.__aggregates = {}
@@ -374,6 +375,14 @@
if cursor is not None:
cursor._reset = True
+ def _reset_already_committed_statements(self):
+ lst = self.__statements_already_committed
+ self.__statements_already_committed = []
+ for weakref in lst:
+ statement = weakref()
+ if statement is not None:
+ statement._reset()
+
@_check_thread_wrap
@_check_closed_wrap
def __call__(self, sql):
@@ -429,15 +438,18 @@
if not self._in_transaction:
return
- # The following line is a KNOWN DIFFERENCE with CPython 2.7.13.
- # More precisely, the corresponding line was removed in the
- # version 2.7.13 of CPython, but this is causing troubles for
- # PyPy (and potentially for CPython too):
- #
- # http://bugs.python.org/issue29006
- #
- # So for now, we keep this line.
- self.__do_all_statements(Statement._reset, False)
+ # PyPy fix for non-refcounting semantics: since 2.7.13 (and in
+ # <= 2.6.x), the statements are not automatically reset upon
+ # commit. However, if this is followed by some specific SQL
+ # operations like "drop table", these open statements come in
+ # the way and cause the "drop table" to fail. On CPython the
+ # problem is much less important because typically all the old
+ # statements are freed already by reference counting. So here,
+ # we copy all the still-alive statements to another list which
+ # is usually ignored, except if we get SQLITE_LOCKED
+ # afterwards---at which point we reset all statements in this
+ # list.
+ self.__statements_already_committed = self.__statements[:]
statement_star = _ffi.new('sqlite3_stmt **')
ret = _lib.sqlite3_prepare_v2(self._db, b"COMMIT", -1,
@@ -866,8 +878,18 @@
self.__statement._set_params(params)
# Actually execute the SQL statement
+
ret = _lib.sqlite3_step(self.__statement._statement)
+ # PyPy: if we get SQLITE_LOCKED, it's probably because
+ # one of the cursors created previously is still alive
+ # and not reset and the operation we're trying to do
+ # makes Sqlite unhappy about that. In that case, we
+ # automatically reset all old cursors and try again.
+ if ret == _lib.SQLITE_LOCKED:
+ self.__connection._reset_already_committed_statements()
+ ret = _lib.sqlite3_step(self.__statement._statement)
+
if ret == _lib.SQLITE_ROW:
if multiple:
raise ProgrammingError("executemany() can only execute DML statements.")
diff --git a/lib_pypy/_testcapimodule.c b/lib_pypy/_testcapimodule.c
--- a/lib_pypy/_testcapimodule.c
+++ b/lib_pypy/_testcapimodule.c
@@ -2856,7 +2856,7 @@
m = PyModule_Create(&_testcapimodule);
if (m == NULL)
return NULL;
-
+
Py_TYPE(&_HashInheritanceTester_Type)=&PyType_Type;
Py_TYPE(&test_structmembersType)=&PyType_Type;
diff --git a/lib_pypy/audioop.py b/lib_pypy/audioop.py
--- a/lib_pypy/audioop.py
+++ b/lib_pypy/audioop.py
@@ -374,7 +374,7 @@
sample_count = _sample_count(cp, size)
- rv = ffi.new("unsigned char[]", len(cp) * 2)
+ rv = ffi.new("char[]", len(cp) * 2)
lib.tostereo(rv, ffi.from_buffer(cp), len(cp), size, fac1, fac2)
return ffi.buffer(rv)[:]
@@ -385,7 +385,7 @@
if len(cp1) != len(cp2):
raise error("Lengths should be the same")
- rv = ffi.new("unsigned char[]", len(cp1))
+ rv = ffi.new("char[]", len(cp1))
lib.add(rv, ffi.from_buffer(cp1), ffi.from_buffer(cp2), len(cp1), size)
return ffi.buffer(rv)[:]
@@ -488,7 +488,7 @@
ceiling = (q + 1) * outrate
nbytes = ceiling * bytes_per_frame
- rv = ffi.new("unsigned char[]", nbytes)
+ rv = ffi.new("char[]", nbytes)
trim_index = lib.ratecv(rv, cp, frame_count, size,
nchannels, inrate, outrate,
state_d, prev_i, cur_i,
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -496,11 +496,6 @@
the rest is kept. If you return an unexpected string from
``__hex__()`` you get an exception (or a crash before CPython 2.7.13).
-* The ``sqlite`` module was updated on 2.7.13 to no longer reset all
- cursors when there is a commit. This causes troubles for PyPy (and
- potentially for CPython too), and so for now we didn't port this change:
- see http://bugs.python.org/issue29006.
-
.. _`is ignored in PyPy`: http://bugs.python.org/issue14621
.. _`little point`: http://events.ccc.de/congress/2012/Fahrplan/events/5152.en.html
.. _`#2072`: https://bitbucket.org/pypy/pypy/issue/2072/
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -26,16 +26,16 @@
Almost!
-The mostly likely stumbling block for any given project is support for
+The most likely stumbling block for any given project is support for
:ref:`extension modules <extension-modules>`. PyPy supports a continually growing
number of extension modules, but so far mostly only those found in the
standard library.
The language features (including builtin types and functions) are very
-complete and well tested, so if your project does not use many
+refined and well tested, so if your project doesn't use many
extension modules there is a good chance that it will work with PyPy.
-We list the differences we know about in :doc:`cpython differences <cpython_differences>`.
+We list the known differences in :doc:`cpython differences <cpython_differences>`.
Module xyz does not work with PyPy: ImportError
@@ -76,10 +76,10 @@
You cannot import *any* extension module in a `sandboxed PyPy`_,
sorry. Even the built-in modules available are very limited.
-Sandboxing in PyPy is a good proof of concept, really safe IMHO, but
-it is only a proof of concept. It seriously requires someone working
-on it. Before this occurs, it can only be used it for "pure Python"
-examples: programs that import mostly nothing (or only pure Python
+Sandboxing in PyPy is a good proof of concept, and is without a doubt
+safe IMHO, however it is only a proof of concept. It currently requires
+some work from a motivated developer. However, until then it can only be used for "pure Python"
+example: programs that import mostly nothing (or only pure Python
modules, recursively).
.. _`sandboxed PyPy`: sandbox.html
diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst
--- a/pypy/doc/getting-started-dev.rst
+++ b/pypy/doc/getting-started-dev.rst
@@ -336,6 +336,6 @@
that fixes some bugs and is translatable.
* :source:`pypy/objspace/std` contains the :ref:`Standard object space <standard-object-space>`. The main file
- is :source:`pypy/objspace/std/objspace.py`. For each type, the files ``xxxtype.py`` and
- ``xxxobject.py`` contain respectively the definition of the type and its
- (default) implementation.
+ is :source:`pypy/objspace/std/objspace.py`. For each type, the file
+ ``xxxobject.py`` contains the implementation for objects of type ``xxx``,
+ as a first approximation. (Some types have multiple implementations.)
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
@@ -110,3 +110,21 @@
Do not recreate the object in PyMemoryView_FromBuffer, rather pass it to
the returned PyMemoryViewObject, to take ownership of it. Fixes a ref leak.
+
+.. branch: issue2464
+
+Give (almost?) all GetSetProperties a valid __objclass__.
+
+.. branch: TreeStain/fixed-typo-line-29-mostly-to-most-1484469416419
+.. branch: TreeStain/main-lines-changed-in-l77-l83-made-para-1484471558033
+
+.. branch: missing-tp_new
+
+Improve mixing app-level classes in c-extensions, especially if the app-level
+class has a ``tp_new`` or ``tp_dealloc``. The issue is that c-extensions expect
+all the method slots to be filled with a function pointer, where app-level will
+search up the mro for an appropriate function at runtime. With this branch we
+now fill many more slots in the c-extenion type objects.
+Also fix for c-extension type that calls ``tp_hash`` during initialization
+(str, unicode types), and fix instantiating c-extension types from built-in
+classes by enforcing an order of instaniation.
diff --git a/pypy/interpreter/test/test_typedef.py b/pypy/interpreter/test/test_typedef.py
--- a/pypy/interpreter/test/test_typedef.py
+++ b/pypy/interpreter/test/test_typedef.py
@@ -143,7 +143,11 @@
pass
def fget(self, space, w_self):
assert self is prop
- prop = typedef.GetSetProperty(fget, use_closure=True)
+ # NB. this GetSetProperty is not copied when creating the
+ # W_TypeObject because of 'cls'. Without it, a duplicate of the
+ # GetSetProperty is taken and it is given the w_objclass that is
+ # the W_TypeObject
+ prop = typedef.GetSetProperty(fget, use_closure=True, cls=W_SomeType)
W_SomeType.typedef = typedef.TypeDef(
'some_type',
x=prop)
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -277,12 +277,15 @@
self.use_closure = use_closure
def copy_for_type(self, w_objclass):
- new = instantiate(GetSetProperty)
- new._init(self.fget, self.fset, self.fdel, self.doc, self.reqcls,
- None, self.use_closure)
- new.name = self.name
- new.w_objclass = w_objclass
- return new
+ if self.objclass_getter is None:
+ new = instantiate(GetSetProperty)
+ new._init(self.fget, self.fset, self.fdel, self.doc, self.reqcls,
+ None, self.use_closure)
+ new.name = self.name
+ new.w_objclass = w_objclass
+ return new
+ else:
+ return self
@unwrap_spec(w_cls = WrappedDefault(None))
def descr_property_get(self, space, w_obj, w_cls=None):
@@ -513,7 +516,7 @@
return lifeline.get_any_weakref(space)
dict_descr = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict,
- doc="dictionary for instance variables")
+ doc="dictionary for instance variables (if defined)")
dict_descr.name = '__dict__'
@@ -548,7 +551,7 @@
return space.newtuple([w_docstring])
weakref_descr = GetSetProperty(descr_get_weakref,
- doc="list of weak references to the object")
+ doc="list of weak references to the object (if defined)")
weakref_descr.name = '__weakref__'
def make_weakref_descr(cls):
diff --git a/pypy/module/_pypyjson/interp_decoder.py b/pypy/module/_pypyjson/interp_decoder.py
--- a/pypy/module/_pypyjson/interp_decoder.py
+++ b/pypy/module/_pypyjson/interp_decoder.py
@@ -109,7 +109,7 @@
else:
raise DecoderError(
"No JSON object could be decoded: unexpected '%s' at" % ch,
- self.pos)
+ i)
def decode_null(self, i):
if (self.ll_chars[i] == 'u' and
@@ -247,7 +247,7 @@
raise DecoderError("Unterminated array starting at", start)
else:
raise DecoderError("Unexpected '%s' when decoding array" % ch,
- self.pos)
+ i-1)
def decode_object(self, i):
start = i
@@ -287,7 +287,7 @@
raise DecoderError("Unterminated object starting at", start)
else:
raise DecoderError("Unexpected '%s' when decoding object" % ch,
- self.pos)
+ i-1)
def decode_string(self, i):
@@ -312,18 +312,17 @@
self.last_type = TYPE_STRING
self.pos = i
return self.space.wrap(content_unicode)
- elif ch == '\\':
- content_so_far = self.getslice(start, i-1)
+ elif ch == '\\' or ch < '\x20':
self.pos = i-1
- return self.decode_string_escaped(start, content_so_far)
- elif ch < '\x20':
- raise DecoderError("Invalid control character at", self.pos-1)
+ return self.decode_string_escaped(start)
- def decode_string_escaped(self, start, content_so_far):
- builder = StringBuilder(len(content_so_far)*2) # just an estimate
- builder.append(content_so_far)
+ def decode_string_escaped(self, start):
i = self.pos
+ builder = StringBuilder((i - start) * 2) # just an estimate
+ assert start >= 0
+ assert i >= 0
+ builder.append_slice(self.s, start, i)
while True:
ch = self.ll_chars[i]
i += 1
@@ -336,27 +335,31 @@
return self.space.wrap(content_unicode)
elif ch == '\\':
i = self.decode_escape_sequence(i, builder)
- elif ch == '\0':
- raise DecoderError("Unterminated string starting at", start)
+ elif ch < '\x20':
+ if ch == '\0':
+ raise DecoderError("Unterminated string starting at",
+ start - 1)
+ else:
+ raise DecoderError("Invalid control character at", i-1)
else:
- builder.append_multiple_char(ch, 1) # we should implement append_char
+ builder.append(ch)
def decode_escape_sequence(self, i, builder):
ch = self.ll_chars[i]
i += 1
- put = builder.append_multiple_char
- if ch == '\\': put('\\', 1)
- elif ch == '"': put('"' , 1)
- elif ch == '/': put('/' , 1)
- elif ch == 'b': put('\b', 1)
- elif ch == 'f': put('\f', 1)
- elif ch == 'n': put('\n', 1)
- elif ch == 'r': put('\r', 1)
- elif ch == 't': put('\t', 1)
+ put = builder.append
+ if ch == '\\': put('\\')
+ elif ch == '"': put('"' )
+ elif ch == '/': put('/' )
+ elif ch == 'b': put('\b')
+ elif ch == 'f': put('\f')
+ elif ch == 'n': put('\n')
+ elif ch == 'r': put('\r')
+ elif ch == 't': put('\t')
elif ch == 'u':
return self.decode_escape_sequence_unicode(i, builder)
else:
- raise DecoderError("Invalid \\escape: %s" % ch, self.pos-1)
+ raise DecoderError("Invalid \\escape: %s" % ch, i-1)
return i
def decode_escape_sequence_unicode(self, i, builder):
diff --git a/pypy/module/_pypyjson/test/test__pypyjson.py b/pypy/module/_pypyjson/test/test__pypyjson.py
--- a/pypy/module/_pypyjson/test/test__pypyjson.py
+++ b/pypy/module/_pypyjson/test/test__pypyjson.py
@@ -215,6 +215,23 @@
assert check("\\\"\b\f\n\r\t") == '\\\\\\"\\b\\f\\n\\r\\t'
assert check("\x07") == "\\u0007"
+ def test_error_position(self):
+ import _pypyjson
+ test_cases = [
+ ('[,', "No JSON object could be decoded: unexpected ',' at", 1),
+ ('{"spam":[}', "No JSON object could be decoded: unexpected '}' at", 9),
+ ('[42:', "Unexpected ':' when decoding array", 3),
+ ('[42 "spam"', "Unexpected '\"' when decoding array", 4),
+ ('[42,]', "No JSON object could be decoded: unexpected ']' at", 4),
+ ('{"spam":[42}', "Unexpected '}' when decoding array", 11),
+ ('["]', 'Unterminated string starting at', 1),
+ ('["spam":', "Unexpected ':' when decoding array", 7),
+ ('[{]', "No JSON object could be decoded: unexpected ']' at", 2),
+ ]
+ for inputtext, errmsg, errpos in test_cases:
+ exc = raises(ValueError, _pypyjson.loads, inputtext)
+ assert exc.value.args == (errmsg, inputtext, errpos)
+
def test_keys_reuse(self):
import _pypyjson
s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]'
diff --git a/pypy/module/_ssl/test/allsans.pem b/pypy/module/_ssl/test/allsans.pem
deleted file mode 100644
--- a/pypy/module/_ssl/test/allsans.pem
+++ /dev/null
@@ -1,37 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOoy7/QOtTjQ0niE
-6uDcTwtkC0R2Tvy1AjVnXohCntZfdzbTGDoYTgXSOLsP8A697jUiJ8VCePGH50xG
-Z4DKnAF3a9O3a9nr2pLXb0iY3XOMv+YEBii7CfI+3oxFYgCl0sMgHzDD2ZTVYAsm
-DWgLUVsE2gHEccRwrM2tPf2EgR+FAgMBAAECgYEA3qyfyYVSeTrTYxO93x6ZaVMu
-A2IZp9zSxMQL9bKiI2GRj+cV2ebSCGbg2btFnD6qBor7FWsmYz+8g6FNN/9sY4az
-61rMqMtQvLBe+7L8w70FeTze4qQ4Y1oQri0qD6tBWhDVlpnbI5Py9bkZKD67yVUk
-elcEA/5x4PrYXkuqsAECQQD80NjT0mDvaY0JOOaQFSEpMv6QiUA8GGX8Xli7IoKb
-tAolPG8rQBa+qSpcWfDMTrWw/aWHuMEEQoP/bVDH9W4FAkEA7SYQbBAKnojZ5A3G
-kOHdV7aeivRQxQk/JN8Fb8oKB9Csvpv/BsuGxPKXHdhFa6CBTTsNRtHQw/szPo4l
-xMIjgQJAPoMxqibR+0EBM6+TKzteSL6oPXsCnBl4Vk/J5vPgkbmR7KUl4+7j8N8J
-b2554TrxKEN/w7CGYZRE6UrRd7ATNQJAWD7Yz41sli+wfPdPU2xo1BHljyl4wMk/
-EPZYbI/PCbdyAH/F935WyQTIjNeEhZc1Zkq6FwdOWw8ns3hrv3rKgQJAHXv1BqUa
-czGPIFxX2TNoqtcl6/En4vrxVB1wzsfzkkDAg98kBl7qsF+S3qujSzKikjeaVbI2
-/CyWR2P3yLtOmA==
------END PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIIDcjCCAtugAwIBAgIJAN5dc9TOWjB7MA0GCSqGSIb3DQEBCwUAMF0xCzAJBgNV
-BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
-IFNvZnR3YXJlIEZvdW5kYXRpb24xEDAOBgNVBAMMB2FsbHNhbnMwHhcNMTYwODA1
-MTAyMTExWhcNMjYwODAzMTAyMTExWjBdMQswCQYDVQQGEwJYWTEXMBUGA1UEBwwO
-Q2FzdGxlIEFudGhyYXgxIzAhBgNVBAoMGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0
-aW9uMRAwDgYDVQQDDAdhbGxzYW5zMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQDqMu/0DrU40NJ4hOrg3E8LZAtEdk78tQI1Z16IQp7WX3c20xg6GE4F0ji7D/AO
-ve41IifFQnjxh+dMRmeAypwBd2vTt2vZ69qS129ImN1zjL/mBAYouwnyPt6MRWIA
-pdLDIB8ww9mU1WALJg1oC1FbBNoBxHHEcKzNrT39hIEfhQIDAQABo4IBODCCATQw
-ggEwBgNVHREEggEnMIIBI4IHYWxsc2Fuc6AeBgMqAwSgFwwVc29tZSBvdGhlciBp
-ZGVudGlmaWVyoDUGBisGAQUCAqArMCmgEBsOS0VSQkVST1MuUkVBTE2hFTAToAMC
-AQGhDDAKGwh1c2VybmFtZYEQdXNlckBleGFtcGxlLm9yZ4IPd3d3LmV4YW1wbGUu
-b3JnpGcwZTELMAkGA1UEBhMCWFkxFzAVBgNVBAcMDkNhc3RsZSBBbnRocmF4MSMw
-IQYDVQQKDBpQeXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEYMBYGA1UEAwwPZGly
-bmFtZSBleGFtcGxlhhdodHRwczovL3d3dy5weXRob24ub3JnL4cEfwAAAYcQAAAA
-AAAAAAAAAAAAAAAAAYgEKgMEBTANBgkqhkiG9w0BAQsFAAOBgQAy16h+F+nOmeiT
-VWR0fc8F/j6FcadbLseAUaogcC15OGxCl4UYpLV88HBkABOoGCpP155qwWTwOrdG
-iYPGJSusf1OnJEbvzFejZf6u078bPd9/ZL4VWLjv+FPGkjd+N+/OaqMvgj8Lu99f
-3Y/C4S7YbHxxwff6C6l2Xli+q6gnuQ==
------END CERTIFICATE-----
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
@@ -39,6 +39,7 @@
from rpython.rlib import rawrefcount
from rpython.rlib import rthread
from rpython.rlib.debug import fatalerror_notb
+from pypy.objspace.std.typeobject import W_TypeObject, find_best_base
DEBUG_WRAPPER = True
@@ -903,6 +904,7 @@
retval = fatal_value
boxed_args = ()
tb = None
+ state = space.fromcache(State)
try:
if not we_are_translated() and DEBUG_WRAPPER:
print >>sys.stderr, callable,
@@ -921,7 +923,6 @@
boxed_args += (arg_conv, )
if pygilstate_ensure:
boxed_args += (args[-1], )
- state = space.fromcache(State)
try:
result = callable(space, *boxed_args)
if not we_are_translated() and DEBUG_WRAPPER:
@@ -967,6 +968,7 @@
except Exception as e:
unexpected_exception(pname, e, tb)
_restore_gil_state(pygilstate_release, gilstate, gil_release, _gil_auto, tid)
+ state.check_and_raise_exception(always=True)
return fatal_value
assert lltype.typeOf(retval) == restype
@@ -1127,6 +1129,34 @@
setup_init_functions(eci, prefix)
return modulename.new(ext='')
+def attach_recursively(space, static_pyobjs, static_objs_w, attached_objs, i):
+ # Start at i but make sure all the base classes are already attached
+ from pypy.module.cpyext.pyobject import get_typedescr, make_ref
+ if i in attached_objs:
+ return
+ py_obj = static_pyobjs[i]
+ w_obj = static_objs_w[i]
+ w_base = None
+ # w_obj can be NotImplemented, which is not a W_TypeObject
+ if isinstance(w_obj, W_TypeObject):
+ bases_w = w_obj.bases_w
+ if bases_w:
+ w_base = find_best_base(bases_w)
+ if w_base:
+ try:
+ j = static_objs_w.index(w_base)
+ except ValueError:
+ j = -1
+ if j >=0 and j not in attached_objs:
+ attach_recursively(space, static_pyobjs, static_objs_w,
+ attached_objs, j)
+ w_type = space.type(w_obj)
+ typedescr = get_typedescr(w_type.layout.typedef)
+ py_obj.c_ob_type = rffi.cast(PyTypeObjectPtr,
+ make_ref(space, w_type))
+ typedescr.attach(space, py_obj, w_obj)
+ attached_objs.append(i)
+
class StaticObjectBuilder(object):
def __init__(self):
@@ -1147,7 +1177,6 @@
def attach_all(self, space):
# this is RPython, called once in pypy-c when it imports cpyext
- from pypy.module.cpyext.pyobject import get_typedescr, make_ref
from pypy.module.cpyext.typeobject import finish_type_1, finish_type_2
from pypy.module.cpyext.pyobject import track_reference
#
@@ -1157,14 +1186,9 @@
track_reference(space, static_pyobjs[i], static_objs_w[i])
#
self.cpyext_type_init = []
+ attached_objs = []
for i in range(len(static_objs_w)):
- py_obj = static_pyobjs[i]
- w_obj = static_objs_w[i]
- w_type = space.type(w_obj)
- typedescr = get_typedescr(w_type.layout.typedef)
- py_obj.c_ob_type = rffi.cast(PyTypeObjectPtr,
- make_ref(space, w_type))
- typedescr.attach(space, py_obj, w_obj)
+ attach_recursively(space, static_pyobjs, static_objs_w, attached_objs, i)
cpyext_type_init = self.cpyext_type_init
self.cpyext_type_init = None
for pto, w_type in cpyext_type_init:
diff --git a/pypy/module/cpyext/bytesobject.py b/pypy/module/cpyext/bytesobject.py
--- a/pypy/module/cpyext/bytesobject.py
+++ b/pypy/module/cpyext/bytesobject.py
@@ -80,14 +80,18 @@
"""
py_str = rffi.cast(PyBytesObject, py_obj)
s = space.str_w(w_obj)
- if py_str.c_ob_size < len(s):
+ len_s = len(s)
+ if py_str.c_ob_size < len_s:
raise oefmt(space.w_ValueError,
"bytes_attach called on object with ob_size %d but trying to store %d",
- py_str.c_ob_size, len(s))
+ py_str.c_ob_size, len_s)
with rffi.scoped_nonmovingbuffer(s) as s_ptr:
- rffi.c_memcpy(py_str.c_ob_sval, s_ptr, len(s))
- py_str.c_ob_sval[len(s)] = '\0'
- py_str.c_ob_shash = space.hash_w(w_obj)
+ rffi.c_memcpy(py_str.c_ob_sval, s_ptr, len_s)
+ py_str.c_ob_sval[len_s] = '\0'
+ # if py_obj has a tp_hash, this will try to call it, but the objects are
+ # not fully linked yet
+ #py_str.c_ob_shash = space.hash_w(w_obj)
+ py_str.c_ob_shash = space.hash_w(space.newbytes(s))
py_str.c_ob_sstate = rffi.cast(rffi.INT, 1) # SSTATE_INTERNED_MORTAL
def bytes_realize(space, py_obj):
@@ -100,7 +104,9 @@
w_type = from_ref(space, rffi.cast(PyObject, py_obj.c_ob_type))
w_obj = space.allocate_instance(W_BytesObject, w_type)
w_obj.__init__(s)
- py_str.c_ob_shash = space.hash_w(w_obj)
+ # if py_obj has a tp_hash, this will try to call it but the object is
+ # not realized yet
+ py_str.c_ob_shash = space.hash_w(space.newbytes(s))
py_str.c_ob_sstate = rffi.cast(rffi.INT, 1) # SSTATE_INTERNED_MORTAL
track_reference(space, py_obj, w_obj)
return w_obj
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -90,11 +90,10 @@
return 0
@cpython_api([rffi.VOIDP], Py_ssize_t, error=CANNOT_FAIL)
-def PyList_GET_SIZE(space, w_list):
+def PyList_GET_SIZE(space, w_obj):
"""Macro form of PyList_Size() without error checking.
"""
- assert isinstance(w_list, W_ListObject)
- return w_list.length()
+ return space.len_w(w_obj)
@cpython_api([PyObject], Py_ssize_t, error=-1)
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
@@ -18,6 +18,7 @@
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.memoryobject import fill_Py_buffer
from pypy.module.cpyext.state import State
+from pypy.module.cpyext import userslot
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.argument import Arguments
from rpython.rlib.buffer import Buffer
@@ -506,6 +507,10 @@
@specialize.memo()
def get_slot_tp_function(space, typedef, name):
+ """Return a description of the slot C function to use for the built-in
+ type for 'typedef'. The 'name' is the slot name. This is a memo
+ function that, after translation, returns one of a built-in finite set.
+ """
key = (typedef, name)
try:
return SLOTS[key]
@@ -543,6 +548,19 @@
return space.call_function(slot_fn, w_self)
handled = True
+ for tp_name, attr in [('tp_hash', '__hash__'),
+ ]:
+ if name == tp_name:
+ slot_fn = w_type.getdictvalue(space, attr)
+ if slot_fn is None:
+ return
+ @slot_function([PyObject], lltype.Signed, 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))
+ handled = True
+
+
# binary functions
for tp_name, attr in [('tp_as_number.c_nb_add', '__add__'),
('tp_as_number.c_nb_subtract', '__sub__'),
@@ -748,7 +766,7 @@
else:
assert False
- function = globals().get(FUNCTION, None)
+ function = getattr(userslot, FUNCTION or '!missing', None)
assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS
if FLAGS:
if wrapper is Ellipsis:
@@ -811,7 +829,7 @@
static slotdef slotdefs[] = {
SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc,
"x.__len__() <==> len(x)"),
- SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc,
+ SQSLOT("__add__", sq_concat, slot_sq_concat, wrap_binaryfunc,
"x.__add__(y) <==> x+y"),
SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc,
"x.__mul__(n) <==> x*n"),
@@ -928,9 +946,7 @@
"x.__call__(...) <==> x(...)", PyWrapperFlag_KEYWORDS),
TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook,
wrap_binaryfunc, "x.__getattribute__('name') <==> x.name"),
- TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""),
- TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""),
- TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""),
+ TPSLOT("__getattr__", tp_getattro, slot_tp_getattr, NULL, ""),
TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr,
"x.__setattr__('name', value) <==> x.name = value"),
TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""),
diff --git a/pypy/module/cpyext/test/foo3.c b/pypy/module/cpyext/test/foo3.c
--- a/pypy/module/cpyext/test/foo3.c
+++ b/pypy/module/cpyext/test/foo3.c
@@ -8,6 +8,24 @@
return newType;
}
+PyObject * typ = NULL;
+PyObject* datetimetype_tp_new(PyTypeObject* metatype, PyObject* args, PyObject* kwds)
+{
+ PyObject* newType;
+ if (typ == NULL)
+ {
+ PyErr_Format(PyExc_TypeError, "could not import datetime.datetime");
+ return NULL;
+ }
+ newType = ((PyTypeObject*)typ)->tp_new(metatype, args, kwds);
+ return newType;
+}
+
+void datetimetype_tp_dealloc(PyObject* self)
+{
+ return ((PyTypeObject*)typ)->tp_dealloc(self);
+}
+
#define BASEFLAGS Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
PyTypeObject footype = {
@@ -58,6 +76,54 @@
/*tp_weaklist*/ 0
};
+PyTypeObject datetimetype = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ /*tp_name*/ "foo3.datetimetype",
+ /*tp_basicsize*/ sizeof(PyTypeObject),
+ /*tp_itemsize*/ 0,
+ /*tp_dealloc*/ datetimetype_tp_dealloc,
+ /*tp_print*/ 0,
+ /*tp_getattr*/ 0,
+ /*tp_setattr*/ 0,
+ /*tp_compare*/ 0,
+ /*tp_repr*/ 0,
+ /*tp_as_number*/ 0,
+ /*tp_as_sequence*/ 0,
+ /*tp_as_mapping*/ 0,
+ /*tp_hash*/ 0,
+ /*tp_call*/ 0,
+ /*tp_str*/ 0,
+ /*tp_getattro*/ 0,
+ /*tp_setattro*/ 0,
+ /*tp_as_buffer*/ 0,
+ /*tp_flags*/ BASEFLAGS,
+ /*tp_doc*/ 0,
+ /*tp_traverse*/ 0,
+ /*tp_clear*/ 0,
+ /*tp_richcompare*/ 0,
+ /*tp_weaklistoffset*/ 0,
+ /*tp_iter*/ 0,
+ /*tp_iternext*/ 0,
+ /*tp_methods*/ 0,
+ /*tp_members*/ 0,
+ /*tp_getset*/ 0,
+ /*tp_base*/ 0, // set to &PyType_Type in module init function (why can it not be done here?)
+ /*tp_dict*/ 0,
+ /*tp_descr_get*/ 0,
+ /*tp_descr_set*/ 0,
+ /*tp_dictoffset*/ 0,
+ /*tp_init*/ 0,
+ /*tp_alloc*/ 0,
+ /*tp_new*/ datetimetype_tp_new,
+ /*tp_free*/ 0,
+ /*tp_is_gc*/ 0,
+ /*tp_bases*/ 0,
+ /*tp_mro*/ 0,
+ /*tp_cache*/ 0,
+ /*tp_subclasses*/ 0,
+ /*tp_weaklist*/ 0
+};
+
static PyMethodDef sbkMethods[] = {{NULL, NULL, 0, NULL}};
static struct PyModuleDef moduledef = {
@@ -81,6 +147,16 @@
PyInit_foo3(void)
{
PyObject *mod, *d;
+ PyObject *module = NULL;
+ module = PyImport_ImportModule("datetime");
+ typ = PyObject_GetAttrString(module, "datetime");
+ Py_DECREF(module);
+ if (!PyType_Check(typ)) {
+ PyErr_Format(PyExc_TypeError, "datetime.datetime is not a type object");
+ return NULL;
+ }
+ datetimetype.tp_base = (PyTypeObject*)typ;
+ PyType_Ready(&datetimetype);
footype.tp_base = &PyType_Type;
PyType_Ready(&footype);
mod = PyModule_Create(&moduledef);
@@ -91,6 +167,8 @@
return NULL;
if (PyDict_SetItemString(d, "footype", (PyObject *)&footype) < 0)
return NULL;
+ if (PyDict_SetItemString(d, "datetimetype", (PyObject *)&datetimetype) < 0)
+ return NULL;
Py_INCREF(&footype);
return mod;
}
diff --git a/pypy/module/cpyext/test/test_dictobject.py b/pypy/module/cpyext/test/test_dictobject.py
--- a/pypy/module/cpyext/test/test_dictobject.py
+++ b/pypy/module/cpyext/test/test_dictobject.py
@@ -1,83 +1,82 @@
import py
from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_api import BaseApiTest, raises_w
from pypy.module.cpyext.api import Py_ssize_tP, PyObjectP, PyTypeObjectPtr
from pypy.module.cpyext.pyobject import make_ref, from_ref
from pypy.interpreter.error import OperationError
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.dictproxyobject import *
+from pypy.module.cpyext.dictobject import *
+from pypy.module.cpyext.pyobject import decref
class TestDictObject(BaseApiTest):
- def test_dict(self, space, api):
- d = api.PyDict_New()
+ def test_dict(self, space):
+ d = PyDict_New(space)
assert space.eq_w(d, space.newdict())
- assert space.eq_w(api.PyDict_GetItem(space.wrap({"a": 72}),
+ assert space.eq_w(PyDict_GetItem(space, space.wrap({"a": 72}),
space.wrap("a")),
space.wrap(72))
- assert api.PyDict_SetItem(d, space.wrap("c"), space.wrap(42)) >= 0
+ PyDict_SetItem(space, d, space.wrap("c"), space.wrap(42))
assert space.eq_w(space.getitem(d, space.wrap("c")),
space.wrap(42))
space.setitem(d, space.wrap("name"), space.wrap(3))
- assert space.eq_w(api.PyDict_GetItem(d, space.wrap("name")),
+ assert space.eq_w(PyDict_GetItem(space, d, space.wrap("name")),
space.wrap(3))
space.delitem(d, space.wrap("name"))
- assert not api.PyDict_GetItem(d, space.wrap("name"))
- assert not api.PyErr_Occurred()
+ assert not PyDict_GetItem(space, d, space.wrap("name"))
buf = rffi.str2charp("name")
- assert not api.PyDict_GetItemString(d, buf)
+ assert not PyDict_GetItemString(space, d, buf)
rffi.free_charp(buf)
- assert not api.PyErr_Occurred()
- assert api.PyDict_Contains(d, space.wrap("c"))
- assert not api.PyDict_Contains(d, space.wrap("z"))
+ assert PyDict_Contains(space, d, space.wrap("c"))
+ assert not PyDict_Contains(space, d, space.wrap("z"))
- assert api.PyDict_DelItem(d, space.wrap("c")) == 0
- assert api.PyDict_DelItem(d, space.wrap("name")) < 0
- assert api.PyErr_Occurred() is space.w_KeyError
- api.PyErr_Clear()
- assert api.PyDict_Size(d) == 0
+ PyDict_DelItem(space, d, space.wrap("c"))
+ with raises_w(space, KeyError):
+ PyDict_DelItem(space, d, space.wrap("name"))
+ assert PyDict_Size(space, d) == 0
space.setitem(d, space.wrap("some_key"), space.wrap(3))
buf = rffi.str2charp("some_key")
- assert api.PyDict_DelItemString(d, buf) == 0
- assert api.PyDict_Size(d) == 0
- assert api.PyDict_DelItemString(d, buf) < 0
- assert api.PyErr_Occurred() is space.w_KeyError
- api.PyErr_Clear()
+ PyDict_DelItemString(space, d, buf)
+ assert PyDict_Size(space, d) == 0
+ with raises_w(space, KeyError):
+ PyDict_DelItemString(space, d, buf)
rffi.free_charp(buf)
d = space.wrap({'a': 'b'})
- api.PyDict_Clear(d)
- assert api.PyDict_Size(d) == 0
+ PyDict_Clear(space, d)
+ assert PyDict_Size(space, d) == 0
- def test_check(self, space, api):
- d = api.PyDict_New()
- assert api.PyDict_Check(d)
- assert api.PyDict_CheckExact(d)
+ def test_check(self, space):
+ d = PyDict_New(space, )
+ assert PyDict_Check(space, d)
+ assert PyDict_CheckExact(space, d)
sub = space.appexec([], """():
class D(dict):
pass
return D""")
d = space.call_function(sub)
- assert api.PyDict_Check(d)
- assert not api.PyDict_CheckExact(d)
+ assert PyDict_Check(space, d)
+ assert not PyDict_CheckExact(space, d)
i = space.wrap(2)
- assert not api.PyDict_Check(i)
- assert not api.PyDict_CheckExact(i)
+ assert not PyDict_Check(space, i)
+ assert not PyDict_CheckExact(space, i)
- def test_keys(self, space, api):
+ def test_keys(self, space):
w_d = space.newdict()
space.setitem(w_d, space.wrap("a"), space.wrap("b"))
- assert space.eq_w(api.PyDict_Keys(w_d), space.wrap(["a"]))
- assert space.eq_w(api.PyDict_Values(w_d), space.wrap(["b"]))
- assert space.eq_w(api.PyDict_Items(w_d), space.wrap([("a", "b")]))
+ assert space.eq_w(PyDict_Keys(space, w_d), space.wrap(["a"]))
+ assert space.eq_w(PyDict_Values(space, w_d), space.wrap(["b"]))
+ assert space.eq_w(PyDict_Items(space, w_d), space.wrap([("a", "b")]))
- def test_merge(self, space, api):
+ def test_merge(self, space):
w_d = space.newdict()
space.setitem(w_d, space.wrap("a"), space.wrap("b"))
@@ -86,35 +85,34 @@
space.setitem(w_d2, space.wrap("c"), space.wrap("d"))
space.setitem(w_d2, space.wrap("e"), space.wrap("f"))
- api.PyDict_Merge(w_d, w_d2, 0)
+ PyDict_Merge(space, w_d, w_d2, 0)
assert space.unwrap(w_d) == dict(a='b', c='d', e='f')
- api.PyDict_Merge(w_d, w_d2, 1)
+ PyDict_Merge(space, w_d, w_d2, 1)
assert space.unwrap(w_d) == dict(a='c', c='d', e='f')
- def test_update(self, space, api):
+ def test_update(self, space):
w_d = space.newdict()
space.setitem(w_d, space.wrap("a"), space.wrap("b"))
- w_d2 = api.PyDict_Copy(w_d)
+ w_d2 = PyDict_Copy(space, w_d)
assert not space.is_w(w_d2, w_d)
space.setitem(w_d, space.wrap("c"), space.wrap("d"))
space.setitem(w_d2, space.wrap("e"), space.wrap("f"))
- api.PyDict_Update(w_d, w_d2)
+ PyDict_Update(space, w_d, w_d2)
assert space.unwrap(w_d) == dict(a='b', c='d', e='f')
- def test_update_doesnt_accept_list_of_tuples(self, space, api):
+ def test_update_doesnt_accept_list_of_tuples(self, space):
w_d = space.newdict()
space.setitem(w_d, space.wrap("a"), space.wrap("b"))
w_d2 = space.wrap([("c", "d"), ("e", "f")])
- api.PyDict_Update(w_d, w_d2)
- assert api.PyErr_Occurred() is space.w_AttributeError
- api.PyErr_Clear()
+ with raises_w(space, AttributeError):
+ PyDict_Update(space, w_d, w_d2)
assert space.unwrap(w_d) == dict(a='b') # unchanged
- def test_iter(self, space, api):
+ def test_iter(self, space):
w_dict = space.sys.getdict(space)
py_dict = make_ref(space, w_dict)
@@ -125,7 +123,7 @@
try:
w_copy = space.newdict()
- while api.PyDict_Next(w_dict, ppos, pkey, pvalue):
+ while PyDict_Next(space, w_dict, ppos, pkey, pvalue):
w_key = from_ref(space, pkey[0])
w_value = from_ref(space, pvalue[0])
space.setitem(w_copy, w_key, w_value)
@@ -134,12 +132,12 @@
lltype.free(pkey, flavor='raw')
lltype.free(pvalue, flavor='raw')
- api.Py_DecRef(py_dict) # release borrowed references
+ decref(space, py_dict) # release borrowed references
assert space.eq_w(space.len(w_copy), space.len(w_dict))
assert space.eq_w(w_copy, w_dict)
- def test_iterkeys(self, space, api):
+ def test_iterkeys(self, space):
w_dict = space.sys.getdict(space)
py_dict = make_ref(space, w_dict)
@@ -151,11 +149,11 @@
values_w = []
try:
ppos[0] = 0
- while api.PyDict_Next(w_dict, ppos, pkey, None):
+ while PyDict_Next(space, w_dict, ppos, pkey, None):
w_key = from_ref(space, pkey[0])
keys_w.append(w_key)
ppos[0] = 0
- while api.PyDict_Next(w_dict, ppos, None, pvalue):
+ while PyDict_Next(space, w_dict, ppos, None, pvalue):
w_value = from_ref(space, pvalue[0])
values_w.append(w_value)
finally:
@@ -163,7 +161,7 @@
lltype.free(pkey, flavor='raw')
lltype.free(pvalue, flavor='raw')
- api.Py_DecRef(py_dict) # release borrowed references
+ decref(space, py_dict) # release borrowed references
assert space.eq_w(space.newlist(keys_w),
space.call_function(
@@ -174,18 +172,18 @@
space.w_list,
space.call_method(w_dict, "values")))
- def test_dictproxy(self, space, api):
+ def test_dictproxy(self, space):
w_dict = space.sys.get('modules')
- w_proxy = api.PyDictProxy_New(w_dict)
+ w_proxy = PyDictProxy_New(space, w_dict)
assert space.contains_w(w_proxy, space.wrap('sys'))
raises(OperationError, space.setitem,
w_proxy, space.wrap('sys'), space.w_None)
raises(OperationError, space.delitem,
w_proxy, space.wrap('sys'))
raises(OperationError, space.call_method, w_proxy, 'clear')
- assert api.PyDictProxy_Check(w_proxy)
+ assert PyDictProxy_Check(space, w_proxy)
- def test_typedict1(self, space, api):
+ def test_typedict1(self, space):
py_type = make_ref(space, space.w_int)
py_dict = rffi.cast(PyTypeObjectPtr, py_type).c_tp_dict
ppos = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
@@ -195,7 +193,7 @@
pvalue = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
try:
w_copy = space.newdict()
- while api.PyDict_Next(py_dict, ppos, pkey, pvalue):
+ while PyDict_Next(space, py_dict, ppos, pkey, pvalue):
w_key = from_ref(space, pkey[0])
w_value = from_ref(space, pvalue[0])
space.setitem(w_copy, w_key, w_value)
@@ -203,7 +201,7 @@
lltype.free(ppos, flavor='raw')
lltype.free(pkey, flavor='raw')
lltype.free(pvalue, flavor='raw')
- api.Py_DecRef(py_type) # release borrowed references
+ decref(space, py_type) # release borrowed references
# do something with w_copy ?
class AppTestDictObject(AppTestCpythonExtensionBase):
diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py
--- a/pypy/module/cpyext/test/test_eval.py
+++ b/pypy/module/cpyext/test/test_eval.py
@@ -1,17 +1,26 @@
+import sys
+import os
+import pytest
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
-from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_api import BaseApiTest, raises_w
+from pypy.module.cpyext.object import PyObject_Size, PyObject_GetItem
+from pypy.module.cpyext.pythonrun import Py_AtExit
from pypy.module.cpyext.eval import (
- Py_single_input, Py_file_input, Py_eval_input, PyCompilerFlags)
-from pypy.module.cpyext.api import (c_fopen, c_fclose, c_fileno,
- Py_ssize_tP, is_valid_fd)
+ Py_single_input, Py_file_input, Py_eval_input, PyCompilerFlags,
+ PyEval_CallObjectWithKeywords, PyObject_CallObject, PyEval_EvalCode,
+ PyRun_SimpleString, PyRun_String, PyRun_StringFlags, PyRun_File,
+ PyEval_GetBuiltins, PyEval_GetLocals, PyEval_GetGlobals,
+ _PyEval_SliceIndex)
+from pypy.module.cpyext.api import (
+ c_fopen, c_fclose, c_fileno, Py_ssize_tP, is_valid_fd)
from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.error import OperationError
from pypy.interpreter.astcompiler import consts
from rpython.tool.udir import udir
-import sys, os
class TestEval(BaseApiTest):
- def test_eval(self, space, api):
+ def test_eval(self, space):
w_l, w_f = space.fixedview(space.appexec([], """():
l = []
def f(arg1, arg2):
@@ -22,7 +31,7 @@
"""))
w_t = space.newtuple([space.wrap(1), space.wrap(2)])
- w_res = api.PyEval_CallObjectWithKeywords(w_f, w_t, None)
+ w_res = PyEval_CallObjectWithKeywords(space, w_f, w_t, None)
assert space.int_w(w_res) == 2
assert space.len_w(w_l) == 2
w_f = space.appexec([], """():
@@ -35,10 +44,10 @@
w_t = space.newtuple([space.w_None, space.w_None])
w_d = space.newdict()
space.setitem(w_d, space.wrap("xyz"), space.wrap(3))
- w_res = api.PyEval_CallObjectWithKeywords(w_f, w_t, w_d)
+ w_res = PyEval_CallObjectWithKeywords(space, w_f, w_t, w_d)
assert space.int_w(w_res) == 21
- def test_call_object(self, space, api):
+ def test_call_object(self, space):
w_l, w_f = space.fixedview(space.appexec([], """():
l = []
def f(arg1, arg2):
@@ -49,7 +58,7 @@
"""))
w_t = space.newtuple([space.wrap(1), space.wrap(2)])
- w_res = api.PyObject_CallObject(w_f, w_t)
+ w_res = PyObject_CallObject(space, w_f, w_t)
assert space.int_w(w_res) == 2
assert space.len_w(w_l) == 2
@@ -61,11 +70,11 @@
""")
w_t = space.newtuple([space.wrap(1), space.wrap(2)])
- w_res = api.PyObject_CallObject(w_f, w_t)
+ w_res = PyObject_CallObject(space, w_f, w_t)
assert space.int_w(w_res) == 10
- def test_evalcode(self, space, api):
+ def test_evalcode(self, space):
w_f = space.appexec([], """():
def f(*args):
assert isinstance(args, tuple)
@@ -77,84 +86,78 @@
w_globals = space.newdict()
w_locals = space.newdict()
space.setitem(w_locals, space.wrap("args"), w_t)
- w_res = api.PyEval_EvalCode(w_f.code, w_globals, w_locals)
+ w_res = PyEval_EvalCode(space, w_f.code, w_globals, w_locals)
assert space.int_w(w_res) == 10
- def test_run_simple_string(self, space, api):
+ def test_run_simple_string(self, space):
def run(code):
buf = rffi.str2charp(code)
try:
- return api.PyRun_SimpleString(buf)
+ return PyRun_SimpleString(space, buf)
finally:
rffi.free_charp(buf)
- assert 0 == run("42 * 43")
+ assert run("42 * 43") == 0 # no error
+ with pytest.raises(OperationError):
+ run("4..3 * 43")
- assert -1 == run("4..3 * 43")
-
- assert api.PyErr_Occurred()
- api.PyErr_Clear()
-
- def test_run_string(self, space, api):
+ def test_run_string(self, space):
def run(code, start, w_globals, w_locals):
buf = rffi.str2charp(code)
try:
- return api.PyRun_String(buf, start, w_globals, w_locals)
+ return PyRun_String(space, buf, start, w_globals, w_locals)
finally:
rffi.free_charp(buf)
w_globals = space.newdict()
assert 42 * 43 == space.unwrap(
run("42 * 43", Py_eval_input, w_globals, w_globals))
- assert api.PyObject_Size(w_globals) == 0
+ assert PyObject_Size(space, w_globals) == 0
assert run("a = 42 * 43", Py_single_input,
w_globals, w_globals) == space.w_None
assert 42 * 43 == space.unwrap(
- api.PyObject_GetItem(w_globals, space.wrap("a")))
+ PyObject_GetItem(space, w_globals, space.wrap("a")))
- def test_run_string_flags(self, space, api):
+ def test_run_string_flags(self, space):
flags = lltype.malloc(PyCompilerFlags, flavor='raw')
flags.c_cf_flags = rffi.cast(rffi.INT, consts.PyCF_SOURCE_IS_UTF8)
w_globals = space.newdict()
buf = rffi.str2charp("a = 'caf\xc3\xa9'")
try:
- api.PyRun_StringFlags(buf, Py_single_input,
- w_globals, w_globals, flags)
+ PyRun_StringFlags(space, buf, Py_single_input, w_globals,
+ w_globals, flags)
finally:
rffi.free_charp(buf)
w_a = space.getitem(w_globals, space.wrap("a"))
assert space.unwrap(w_a) == u'caf\xe9'
lltype.free(flags, flavor='raw')
- def test_run_file(self, space, api):
+ def test_run_file(self, space):
filepath = udir / "cpyext_test_runfile.py"
filepath.write("raise ZeroDivisionError")
fp = c_fopen(str(filepath), "rb")
filename = rffi.str2charp(str(filepath))
w_globals = w_locals = space.newdict()
- api.PyRun_File(fp, filename, Py_file_input, w_globals, w_locals)
+ with raises_w(space, ZeroDivisionError):
+ PyRun_File(space, fp, filename, Py_file_input, w_globals, w_locals)
c_fclose(fp)
- assert api.PyErr_Occurred() is space.w_ZeroDivisionError
- api.PyErr_Clear()
# try again, but with a closed file
fp = c_fopen(str(filepath), "rb")
os.close(c_fileno(fp))
- api.PyRun_File(fp, filename, Py_file_input, w_globals, w_locals)
+ with raises_w(space, IOError):
+ PyRun_File(space, fp, filename, Py_file_input, w_globals, w_locals)
if is_valid_fd(c_fileno(fp)):
c_fclose(fp)
- assert api.PyErr_Occurred() is space.w_IOError
- api.PyErr_Clear()
-
rffi.free_charp(filename)
- def test_getbuiltins(self, space, api):
- assert api.PyEval_GetBuiltins() is space.builtin.w_dict
+ def test_getbuiltins(self, space):
+ assert PyEval_GetBuiltins(space) is space.builtin.w_dict
def cpybuiltins(space):
- return api.PyEval_GetBuiltins()
+ return PyEval_GetBuiltins(space)
w_cpybuiltins = space.wrap(interp2app(cpybuiltins))
w_result = space.appexec([w_cpybuiltins], """(cpybuiltins):
@@ -168,13 +171,13 @@
""")
assert space.len_w(w_result) == 1
- def test_getglobals(self, space, api):
- assert api.PyEval_GetLocals() is None
- assert api.PyEval_GetGlobals() is None
+ def test_getglobals(self, space):
+ assert PyEval_GetLocals(space) is None
+ assert PyEval_GetGlobals(space) is None
def cpyvars(space):
- return space.newtuple([api.PyEval_GetGlobals(),
- api.PyEval_GetLocals()])
+ return space.newtuple([PyEval_GetGlobals(space),
+ PyEval_GetLocals(space)])
w_cpyvars = space.wrap(interp2app(cpyvars))
w_result = space.appexec([w_cpyvars], """(cpyvars):
@@ -186,26 +189,26 @@
assert sorted(locals) == ['cpyvars', 'x']
assert sorted(globals) == ['__builtins__', 'anonymous', 'y']
- def test_sliceindex(self, space, api):
+ def test_sliceindex(self, space):
pi = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
- assert api._PyEval_SliceIndex(space.w_None, pi) == 0
- api.PyErr_Clear()
+ with pytest.raises(OperationError):
+ _PyEval_SliceIndex(space, space.w_None, pi)
- assert api._PyEval_SliceIndex(space.wrap(123), pi) == 1
+ assert _PyEval_SliceIndex(space, space.wrap(123), pi) == 1
assert pi[0] == 123
- assert api._PyEval_SliceIndex(space.wrap(1 << 66), pi) == 1
+ assert _PyEval_SliceIndex(space, space.wrap(1 << 66), pi) == 1
assert pi[0] == sys.maxint
lltype.free(pi, flavor='raw')
- def test_atexit(self, space, api):
+ def test_atexit(self, space):
lst = []
def func():
lst.append(42)
- api.Py_AtExit(func)
+ Py_AtExit(space, func)
cpyext = space.getbuiltinmodule('cpyext')
- cpyext.shutdown(space) # simulate shutdown
+ cpyext.shutdown(space) # simulate shutdown
assert lst == [42]
class AppTestCall(AppTestCpythonExtensionBase):
@@ -269,6 +272,7 @@
return res;
"""),
])
+
def f(*args):
return args
assert module.call_func(f) == (None,)
@@ -323,7 +327,7 @@
])
assert module.get_flags() == (0, 0)
- ns = {'module':module}
+ ns = {'module': module}
if not hasattr(sys, 'pypy_version_info'): # no barry_as_FLUFL on pypy
exec("""from __future__ import barry_as_FLUFL \nif 1:
def nested_flags():
diff --git a/pypy/module/cpyext/test/test_floatobject.py b/pypy/module/cpyext/test/test_floatobject.py
--- a/pypy/module/cpyext/test/test_floatobject.py
+++ b/pypy/module/cpyext/test/test_floatobject.py
@@ -1,36 +1,40 @@
+import pytest
+from pypy.interpreter.error import OperationError
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from rpython.rtyper.lltypesystem import rffi
+from pypy.module.cpyext.floatobject import (
+ PyFloat_FromDouble, PyFloat_AsDouble, PyFloat_AS_DOUBLE, PyNumber_Float,
+ _PyFloat_Unpack4, _PyFloat_Unpack8)
class TestFloatObject(BaseApiTest):
- def test_floatobject(self, space, api):
- assert space.unwrap(api.PyFloat_FromDouble(3.14)) == 3.14
- assert api.PyFloat_AsDouble(space.wrap(23.45)) == 23.45
- assert api.PyFloat_AS_DOUBLE(space.wrap(23.45)) == 23.45
+ def test_floatobject(self, space):
+ assert space.unwrap(PyFloat_FromDouble(space, 3.14)) == 3.14
+ assert PyFloat_AsDouble(space, space.wrap(23.45)) == 23.45
+ assert PyFloat_AS_DOUBLE(space, space.wrap(23.45)) == 23.45
+ with pytest.raises(OperationError):
+ PyFloat_AsDouble(space, space.w_None)
- assert api.PyFloat_AsDouble(space.w_None) == -1
- api.PyErr_Clear()
-
- def test_coerce(self, space, api):
- assert space.type(api.PyNumber_Float(space.wrap(3))) is space.w_float
- assert space.type(api.PyNumber_Float(space.wrap("3"))) is space.w_float
+ def test_coerce(self, space):
+ assert space.type(PyNumber_Float(space, space.wrap(3))) is space.w_float
+ assert space.type(PyNumber_Float(space, space.wrap("3"))) is space.w_float
w_obj = space.appexec([], """():
class Coerce(object):
def __float__(self):
return 42.5
return Coerce()""")
- assert space.eq_w(api.PyNumber_Float(w_obj), space.wrap(42.5))
+ assert space.eq_w(PyNumber_Float(space, w_obj), space.wrap(42.5))
- def test_unpack(self, space, api):
+ def test_unpack(self, space):
with rffi.scoped_str2charp("\x9a\x99\x99?") as ptr:
- assert abs(api._PyFloat_Unpack4(ptr, 1) - 1.2) < 1e-7
+ assert abs(_PyFloat_Unpack4(space, ptr, 1) - 1.2) < 1e-7
with rffi.scoped_str2charp("?\x99\x99\x9a") as ptr:
- assert abs(api._PyFloat_Unpack4(ptr, 0) - 1.2) < 1e-7
+ assert abs(_PyFloat_Unpack4(space, ptr, 0) - 1.2) < 1e-7
with rffi.scoped_str2charp("\x1f\x85\xebQ\xb8\x1e\t@") as ptr:
- assert abs(api._PyFloat_Unpack8(ptr, 1) - 3.14) < 1e-15
+ assert abs(_PyFloat_Unpack8(space, ptr, 1) - 3.14) < 1e-15
with rffi.scoped_str2charp("@\t\x1e\xb8Q\xeb\x85\x1f") as ptr:
- assert abs(api._PyFloat_Unpack8(ptr, 0) - 3.14) < 1e-15
+ assert abs(_PyFloat_Unpack8(space, ptr, 0) - 3.14) < 1e-15
class AppTestFloatObject(AppTestCpythonExtensionBase):
def test_fromstring(self):
@@ -79,8 +83,6 @@
assert math.isinf(neginf)
def test_macro_accepts_wrong_pointer_type(self):
- import math
-
module = self.import_extension('foo', [
("test_macros", "METH_NOARGS",
"""
diff --git a/pypy/module/cpyext/test/test_funcobject.py b/pypy/module/cpyext/test/test_funcobject.py
--- a/pypy/module/cpyext/test/test_funcobject.py
+++ b/pypy/module/cpyext/test/test_funcobject.py
@@ -1,16 +1,18 @@
-from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from rpython.rtyper.lltypesystem import rffi
from pypy.module.cpyext.test.test_api import BaseApiTest
-from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
+from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref, decref
+from pypy.module.cpyext.methodobject import PyClassMethod_New
from pypy.module.cpyext.funcobject import (
- PyFunctionObject, PyCodeObject, CODE_FLAGS)
-from pypy.interpreter.function import Function, Method
+ PyFunctionObject, PyCodeObject, CODE_FLAGS, PyMethod_Function,
+ PyMethod_Self, PyMethod_New, PyFunction_GetCode,
+ PyCode_NewEmpty, PyCode_GetNumFree)
+from pypy.interpreter.function import Function
from pypy.interpreter.pycode import PyCode
globals().update(CODE_FLAGS)
class TestFunctionObject(BaseApiTest):
- def test_function(self, space, api):
+ def test_function(self, space):
w_function = space.appexec([], """():
def f(): pass
return f
@@ -19,10 +21,10 @@
assert (from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is
space.gettypeobject(Function.typedef))
assert "f" == space.unwrap(
- from_ref(space, rffi.cast(PyFunctionObject, ref).c_func_name))
- api.Py_DecRef(ref)
+ from_ref(space, rffi.cast(PyFunctionObject, ref).c_func_name))
+ decref(space, ref)
- def test_method(self, space, api):
+ def test_method(self, space):
w_method = space.appexec([], """():
class C(list):
def method(self): pass
@@ -32,29 +34,29 @@
w_function = space.getattr(w_method, space.wrap("__func__"))
w_self = space.getattr(w_method, space.wrap("__self__"))
- assert space.is_w(api.PyMethod_Function(w_method), w_function)
- assert space.is_w(api.PyMethod_Self(w_method), w_self)
+ assert space.is_w(PyMethod_Function(space, w_method), w_function)
+ assert space.is_w(PyMethod_Self(space, w_method), w_self)
- w_method2 = api.PyMethod_New(w_function, w_self)
+ w_method2 = PyMethod_New(space, w_function, w_self)
assert space.eq_w(w_method, w_method2)
- def test_getcode(self, space, api):
+ def test_getcode(self, space):
w_function = space.appexec([], """():
def func(x, y, z): return x
return func
""")
- w_code = api.PyFunction_GetCode(w_function)
+ w_code = PyFunction_GetCode(space, w_function)
assert w_code.co_name == "func"
ref = make_ref(space, w_code)
assert (from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is
space.gettypeobject(PyCode.typedef))
assert "func" == space.unwrap(
- from_ref(space, rffi.cast(PyCodeObject, ref).c_co_name))
+ from_ref(space, rffi.cast(PyCodeObject, ref).c_co_name))
assert 3 == rffi.cast(PyCodeObject, ref).c_co_argcount
- api.Py_DecRef(ref)
+ decref(space, ref)
- def test_co_flags(self, space, api):
+ def test_co_flags(self, space):
def get_flags(signature, body="pass"):
w_code = space.appexec([], """():
def func(%s): %s
@@ -62,36 +64,36 @@
""" % (signature, body))
ref = make_ref(space, w_code)
co_flags = rffi.cast(PyCodeObject, ref).c_co_flags
- api.Py_DecRef(ref)
+ decref(space, ref)
return co_flags
assert get_flags("x") == CO_NESTED | CO_OPTIMIZED | CO_NEWLOCALS
assert get_flags("x, *args") & CO_VARARGS
assert get_flags("x, **kw") & CO_VARKEYWORDS
assert get_flags("x", "yield x") & CO_GENERATOR
- def test_newcode(self, space, api):
+ def test_newcode(self, space):
filename = rffi.str2charp('filename')
funcname = rffi.str2charp('funcname')
- w_code = api.PyCode_NewEmpty(filename, funcname, 3)
+ w_code = PyCode_NewEmpty(space, filename, funcname, 3)
assert w_code.co_filename == 'filename'
assert w_code.co_firstlineno == 3
ref = make_ref(space, w_code)
assert "filename" == space.unwrap(
from_ref(space, rffi.cast(PyCodeObject, ref).c_co_filename))
- api.Py_DecRef(ref)
+ decref(space, ref)
rffi.free_charp(filename)
rffi.free_charp(funcname)
- def test_getnumfree(self, space, api):
+ def test_getnumfree(self, space):
w_function = space.appexec([], """():
a = 5
def method(x): return a, x
return method
""")
- assert api.PyCode_GetNumFree(w_function.code) == 1
+ assert PyCode_GetNumFree(space, w_function.code) == 1
- def test_classmethod(self, space, api):
+ def test_classmethod(self, space):
w_function = space.appexec([], """():
def method(x): return x
return method
@@ -103,6 +105,7 @@
space.setattr(w_class, space.wrap("method"), w_function)
assert space.is_w(space.call_method(w_instance, "method"), w_instance)
# now a classmethod
- w_classmethod = api.PyClassMethod_New(w_function)
+ w_classmethod = PyClassMethod_New(space, w_function)
space.setattr(w_class, space.wrap("classmethod"), w_classmethod)
- assert space.is_w(space.call_method(w_instance, "classmethod"), w_class)
+ assert space.is_w(
+ space.call_method(w_instance, "classmethod"), w_class)
diff --git a/pypy/module/cpyext/test/test_import.py b/pypy/module/cpyext/test/test_import.py
--- a/pypy/module/cpyext/test/test_import.py
+++ b/pypy/module/cpyext/test/test_import.py
@@ -1,48 +1,51 @@
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.import_ import *
+from pypy.module.cpyext.import_ import (
+ _PyImport_AcquireLock, _PyImport_ReleaseLock)
from rpython.rtyper.lltypesystem import rffi
class TestImport(BaseApiTest):
- def test_import(self, space, api):
- stat = api.PyImport_Import(space.wrap("stat"))
+ def test_import(self, space):
+ stat = PyImport_Import(space, space.wrap("stat"))
assert stat
assert space.getattr(stat, space.wrap("S_IMODE"))
- def test_addmodule(self, space, api):
+ def test_addmodule(self, space):
with rffi.scoped_str2charp("sys") as modname:
- w_sys = api.PyImport_AddModule(modname)
+ w_sys = PyImport_AddModule(space, modname)
assert w_sys is space.sys
with rffi.scoped_str2charp("foobar") as modname:
- w_foobar = api.PyImport_AddModule(modname)
+ w_foobar = PyImport_AddModule(space, modname)
assert space.str_w(space.getattr(w_foobar,
space.wrap('__name__'))) == 'foobar'
def test_getmoduledict(self, space, api):
testmod = "contextlib"
- w_pre_dict = api.PyImport_GetModuleDict()
+ w_pre_dict = PyImport_GetModuleDict(space, )
assert not space.contains_w(w_pre_dict, space.wrap(testmod))
with rffi.scoped_str2charp(testmod) as modname:
- w_module = api.PyImport_ImportModule(modname)
+ w_module = PyImport_ImportModule(space, modname)
print w_module
assert w_module
- w_dict = api.PyImport_GetModuleDict()
+ w_dict = PyImport_GetModuleDict(space, )
assert space.contains_w(w_dict, space.wrap(testmod))
- def test_reload(self, space, api):
- stat = api.PyImport_Import(space.wrap("stat"))
+ def test_reload(self, space):
+ stat = PyImport_Import(space, space.wrap("stat"))
space.delattr(stat, space.wrap("S_IMODE"))
- stat = api.PyImport_ReloadModule(stat)
+ stat = PyImport_ReloadModule(space, stat)
assert space.getattr(stat, space.wrap("S_IMODE"))
- def test_lock(self, space, api):
+ def test_lock(self, space):
# "does not crash"
- api._PyImport_AcquireLock()
- api._PyImport_AcquireLock()
- api._PyImport_ReleaseLock()
- api._PyImport_ReleaseLock()
+ _PyImport_AcquireLock(space, )
+ _PyImport_AcquireLock(space, )
+ _PyImport_ReleaseLock(space, )
+ _PyImport_ReleaseLock(space, )
class AppTestImportLogic(AppTestCpythonExtensionBase):
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
@@ -30,12 +30,14 @@
assert view.c_len == 5
o = rffi.charp2str(view.c_buf)
assert o == 'hello'
- w_mv = from_ref(space, api.PyMemoryView_FromBuffer(view))
+ ref = api.PyMemoryView_FromBuffer(view)
+ w_mv = from_ref(space, ref)
for f in ('format', 'itemsize', 'ndim', 'readonly',
'shape', 'strides', 'suboffsets'):
w_f = space.wrap(f)
assert space.eq_w(space.getattr(w_mv, w_f),
space.getattr(w_memoryview, w_f))
+ api.Py_DecRef(ref)
class AppTestPyBuffer_FillInfo(AppTestCpythonExtensionBase):
def test_fillWithObject(self):
diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -90,7 +90,7 @@
api.PyErr_WriteUnraisable(w_where)
space.call_method(space.sys.get('stderr'), "flush")
out, err = capfd.readouterr()
- assert "Exception ValueError: 'message' in 'location' ignored" == err.strip()
+ assert "Exception ignored in: 'location'\nValueError: message" == err.strip()
@pytest.mark.skipif(True, reason='not implemented yet')
def test_interrupt_occurred(self, space, api):
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -2,6 +2,7 @@
from rpython.rtyper.lltypesystem import rffi
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.api import generic_cpy_call
from pypy.module.cpyext.pyobject import make_ref, from_ref
from pypy.module.cpyext.typeobject import PyTypeObjectPtr
@@ -634,26 +635,6 @@
assert module.tp_init(list, x, ("hi",)) is None
assert x == ["h", "i"]
- def test_tp_str(self):
- module = self.import_extension('foo', [
- ("tp_str", "METH_VARARGS",
- '''
- PyTypeObject *type = (PyTypeObject *)PyTuple_GET_ITEM(args, 0);
- PyObject *obj = PyTuple_GET_ITEM(args, 1);
- if (!type->tp_str)
- {
- PyErr_SetNone(PyExc_ValueError);
- return NULL;
- }
- return type->tp_str(obj);
- '''
- )
- ])
- class D(int):
- def __str__(self):
- return "more text"
- assert module.tp_str(int, D(42)) == "42"
-
def test_mp_ass_subscript(self):
module = self.import_extension('foo', [
("new_obj", "METH_NOARGS",
@@ -942,9 +923,12 @@
assert (d + a) == 5
assert pow(d,b) == 16
- def test_tp_new_in_subclass_of_type(self):
+ def test_tp_new_in_subclass(self):
+ import datetime
module = self.import_module(name='foo3')
module.footype("X", (object,), {})
+ a = module.datetimetype(1, 1, 1)
+ assert isinstance(a, module.datetimetype)
def test_app_subclass_of_c_type(self):
import sys
@@ -1130,7 +1114,6 @@
# class X(object, metaclass=FooType): pass
X = FooType('X', (object,), {})
- print(repr(X))
X()
def test_multiple_inheritance3(self):
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -1,5 +1,6 @@
# encoding: utf-8
-from pypy.module.cpyext.test.test_api import BaseApiTest
+import pytest
+from pypy.module.cpyext.test.test_api import BaseApiTest, raises_w
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from pypy.module.cpyext.unicodeobject import (
Py_UNICODE, PyUnicodeObject, new_empty_unicode)
@@ -7,6 +8,7 @@
from pypy.module.cpyext.pyobject import Py_DecRef, from_ref
from rpython.rtyper.lltypesystem import rffi, lltype
import sys, py
+from pypy.module.cpyext.unicodeobject import *
class AppTestUnicodeObject(AppTestCpythonExtensionBase):
def test_unicodeobject(self):
@@ -209,44 +211,45 @@
assert module.test_macro_invocations() == u''
class TestUnicode(BaseApiTest):
- def test_unicodeobject(self, space, api):
- assert api.PyUnicode_GET_SIZE(space.wrap(u'späm')) == 4
- assert api.PyUnicode_GetSize(space.wrap(u'späm')) == 4
+ def test_unicodeobject(self, space):
+ assert PyUnicode_GET_SIZE(space, space.wrap(u'späm')) == 4
+ assert PyUnicode_GetSize(space, space.wrap(u'späm')) == 4
unichar = rffi.sizeof(Py_UNICODE)
- assert api.PyUnicode_GET_DATA_SIZE(space.wrap(u'späm')) == 4 * unichar
+ assert PyUnicode_GET_DATA_SIZE(space, space.wrap(u'späm')) == 4 * unichar
- encoding = rffi.charp2str(api.PyUnicode_GetDefaultEncoding())
+ encoding = rffi.charp2str(PyUnicode_GetDefaultEncoding(space, ))
w_default_encoding = space.call_function(
space.sys.get('getdefaultencoding')
)
assert encoding == space.unwrap(w_default_encoding)
- def test_AS(self, space, api):
+ def test_AS(self, space):
word = space.wrap(u'spam')
- array = rffi.cast(rffi.CWCHARP, api.PyUnicode_AS_DATA(word))
- array2 = api.PyUnicode_AS_UNICODE(word)
- array3 = api.PyUnicode_AsUnicode(word)
+ array = rffi.cast(rffi.CWCHARP, PyUnicode_AS_DATA(space, word))
+ array2 = PyUnicode_AS_UNICODE(space, word)
+ array3 = PyUnicode_AsUnicode(space, word)
for (i, char) in enumerate(space.unwrap(word)):
assert array[i] == char
assert array2[i] == char
assert array3[i] == char
- self.raises(space, api, TypeError, api.PyUnicode_AsUnicode,
- space.newbytes('spam'))
+ with raises_w(space, TypeError):
+ PyUnicode_AsUnicode(space, space.newbytes('spam'))
utf_8 = rffi.str2charp('utf-8')
- encoded = api.PyUnicode_AsEncodedString(space.wrap(u'späm'),
+ encoded = PyUnicode_AsEncodedString(space, space.wrap(u'späm'),
utf_8, None)
assert space.unwrap(encoded) == 'sp\xc3\xa4m'
- encoded_obj = api.PyUnicode_AsEncodedObject(space.wrap(u'späm'),
+ encoded_obj = PyUnicode_AsEncodedObject(space, space.wrap(u'späm'),
utf_8, None)
assert space.eq_w(encoded, encoded_obj)
- self.raises(space, api, TypeError, api.PyUnicode_AsEncodedString,
- space.newtuple([1, 2, 3]), None, None)
- self.raises(space, api, TypeError, api.PyUnicode_AsEncodedString,
- space.newbytes(''), None, None)
+ with raises_w(space, TypeError):
+ PyUnicode_AsEncodedString(
+ space, space.newtuple([1, 2, 3]), None, None)
+ with raises_w(space, TypeError):
+ PyUnicode_AsEncodedString(space, space.newbytes(''), None, None)
ascii = rffi.str2charp('ascii')
replace = rffi.str2charp('replace')
- encoded = api.PyUnicode_AsEncodedString(space.wrap(u'späm'),
+ encoded = PyUnicode_AsEncodedString(space, space.wrap(u'späm'),
ascii, replace)
assert space.unwrap(encoded) == 'sp?m'
rffi.free_charp(utf_8)
@@ -254,45 +257,45 @@
rffi.free_charp(ascii)
buf = rffi.unicode2wcharp(u"12345")
- api.PyUnicode_AsWideChar(space.wrap(u'longword'), buf, 5)
+ PyUnicode_AsWideChar(space, space.wrap(u'longword'), buf, 5)
assert rffi.wcharp2unicode(buf) == 'longw'
- api.PyUnicode_AsWideChar(space.wrap(u'a'), buf, 5)
+ PyUnicode_AsWideChar(space, space.wrap(u'a'), buf, 5)
assert rffi.wcharp2unicode(buf) == 'a'
rffi.free_wcharp(buf)
- def test_fromstring(self, space, api):
+ def test_fromstring(self, space):
s = rffi.str2charp(u'sp\x09m'.encode("utf-8"))
- w_res = api.PyUnicode_FromString(s)
+ w_res = PyUnicode_FromString(space, s)
assert space.unwrap(w_res) == u'sp\x09m'
- res = api.PyUnicode_FromStringAndSize(s, 4)
+ res = PyUnicode_FromStringAndSize(space, s, 4)
w_res = from_ref(space, res)
- api.Py_DecRef(res)
+ Py_DecRef(space, res)
assert space.unwrap(w_res) == u'sp\x09m'
rffi.free_charp(s)
- def test_internfromstring(self, space, api):
+ def test_internfromstring(self, space):
with rffi.scoped_str2charp('foo') as s:
- w_res = api.PyUnicode_InternFromString(s)
+ w_res = PyUnicode_InternFromString(space, s)
assert space.unwrap(w_res) == u'foo'
- w_res2 = api.PyUnicode_InternFromString(s)
+ w_res2 = PyUnicode_InternFromString(space, s)
assert w_res is w_res2
- def test_unicode_resize(self, space, api):
+ def test_unicode_resize(self, space):
py_uni = new_empty_unicode(space, 10)
ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
py_uni.c_buffer[0] = u'a'
py_uni.c_buffer[1] = u'b'
py_uni.c_buffer[2] = u'c'
ar[0] = rffi.cast(PyObject, py_uni)
- api.PyUnicode_Resize(ar, 3)
+ PyUnicode_Resize(space, ar, 3)
py_uni = rffi.cast(PyUnicodeObject, ar[0])
assert py_uni.c_length == 3
assert py_uni.c_buffer[1] == u'b'
assert py_uni.c_buffer[3] == u'\x00'
# the same for growing
ar[0] = rffi.cast(PyObject, py_uni)
- api.PyUnicode_Resize(ar, 10)
+ PyUnicode_Resize(space, ar, 10)
py_uni = rffi.cast(PyUnicodeObject, ar[0])
assert py_uni.c_length == 10
assert py_uni.c_buffer[1] == 'b'
@@ -300,47 +303,46 @@
Py_DecRef(space, ar[0])
lltype.free(ar, flavor='raw')
- def test_AsUTF8String(self, space, api):
+ def test_AsUTF8String(self, space):
w_u = space.wrap(u'sp\x09m')
- w_res = api.PyUnicode_AsUTF8String(w_u)
+ w_res = PyUnicode_AsUTF8String(space, w_u)
assert space.type(w_res) is space.w_str
assert space.unwrap(w_res) == 'sp\tm'
- def test_decode_utf8(self, space, api):
+ def test_decode_utf8(self, space):
u = rffi.str2charp(u'sp\x134m'.encode("utf-8"))
- w_u = api.PyUnicode_DecodeUTF8(u, 5, None)
+ w_u = PyUnicode_DecodeUTF8(space, u, 5, None)
assert space.type(w_u) is space.w_unicode
assert space.unwrap(w_u) == u'sp\x134m'
- w_u = api.PyUnicode_DecodeUTF8(u, 2, None)
+ w_u = PyUnicode_DecodeUTF8(space, u, 2, None)
assert space.type(w_u) is space.w_unicode
assert space.unwrap(w_u) == 'sp'
rffi.free_charp(u)
- def test_encode_utf8(self, space, api):
+ def test_encode_utf8(self, space):
u = rffi.unicode2wcharp(u'sp\x09m')
- w_s = api.PyUnicode_EncodeUTF8(u, 4, None)
+ w_s = PyUnicode_EncodeUTF8(space, u, 4, None)
assert space.unwrap(w_s) == u'sp\x09m'.encode('utf-8')
rffi.free_wcharp(u)
- def test_encode_decimal(self, space, api):
+ def test_encode_decimal(self, space):
with rffi.scoped_unicode2wcharp(u' (12, 35 ABC)') as u:
with rffi.scoped_alloc_buffer(20) as buf:
- res = api.PyUnicode_EncodeDecimal(u, 13, buf.raw, None)
+ res = PyUnicode_EncodeDecimal(space, u, 13, buf.raw, None)
s = rffi.charp2str(buf.raw)
assert res == 0
assert s == ' (12, 35 ABC)'
with rffi.scoped_unicode2wcharp(u' (12, \u1234\u1235)') as u:
with rffi.scoped_alloc_buffer(20) as buf:
- res = api.PyUnicode_EncodeDecimal(u, 9, buf.raw, None)
- assert res == -1
- api.PyErr_Clear()
+ with pytest.raises(OperationError):
+ PyUnicode_EncodeDecimal(space, u, 9, buf.raw, None)
with rffi.scoped_unicode2wcharp(u' (12, \u1234\u1235)') as u:
with rffi.scoped_alloc_buffer(20) as buf:
with rffi.scoped_str2charp("replace") as errors:
- res = api.PyUnicode_EncodeDecimal(u, 9, buf.raw,
+ res = PyUnicode_EncodeDecimal(space, u, 9, buf.raw,
errors)
s = rffi.charp2str(buf.raw)
assert res == 0
@@ -349,117 +351,117 @@
with rffi.scoped_unicode2wcharp(u'12\u1234') as u:
with rffi.scoped_alloc_buffer(20) as buf:
with rffi.scoped_str2charp("xmlcharrefreplace") as errors:
- res = api.PyUnicode_EncodeDecimal(u, 3, buf.raw,
+ res = PyUnicode_EncodeDecimal(space, u, 3, buf.raw,
errors)
s = rffi.charp2str(buf.raw)
assert res == 0
assert s == "12ሴ"
- def test_encode_fsdefault(self, space, api):
+ def test_encode_fsdefault(self, space):
w_u = space.wrap(u'späm')
- w_s = api.PyUnicode_EncodeFSDefault(w_u)
+ w_s = PyUnicode_EncodeFSDefault(space, w_u)
if w_s is None:
- api.PyErr_Clear()
+ PyErr_Clear(space)
py.test.skip("Requires a unicode-aware fsencoding")
with rffi.scoped_str2charp(space.str_w(w_s)) as encoded:
- w_decoded = api.PyUnicode_DecodeFSDefaultAndSize(encoded, space.len_w(w_s))
+ w_decoded = PyUnicode_DecodeFSDefaultAndSize(space, encoded, space.len_w(w_s))
assert space.eq_w(w_decoded, w_u)
- w_decoded = api.PyUnicode_DecodeFSDefault(encoded)
+ w_decoded = PyUnicode_DecodeFSDefault(space, encoded)
assert space.eq_w(w_decoded, w_u)
- def test_fsconverter(self, space, api):
+ def test_fsconverter(self, space):
# Input is bytes
w_input = space.newbytes("test")
with lltype.scoped_alloc(PyObjectP.TO, 1) as result:
# Decoder
- ret = api.PyUnicode_FSDecoder(w_input, result)
+ ret = PyUnicode_FSDecoder(space, w_input, result)
assert ret == Py_CLEANUP_SUPPORTED
assert space.isinstance_w(from_ref(space, result[0]), space.w_unicode)
- assert api.PyUnicode_FSDecoder(None, result) == 1
+ assert PyUnicode_FSDecoder(space, None, result) == 1
# Converter
- ret = api.PyUnicode_FSConverter(w_input, result)
+ ret = PyUnicode_FSConverter(space, w_input, result)
assert ret == Py_CLEANUP_SUPPORTED
assert space.eq_w(from_ref(space, result[0]), w_input)
- assert api.PyUnicode_FSDecoder(None, result) == 1
+ assert PyUnicode_FSDecoder(space, None, result) == 1
# Input is unicode
w_input = space.wrap("test")
with lltype.scoped_alloc(PyObjectP.TO, 1) as result:
# Decoder
- ret = api.PyUnicode_FSDecoder(w_input, result)
+ ret = PyUnicode_FSDecoder(space, w_input, result)
assert ret == Py_CLEANUP_SUPPORTED
assert space.eq_w(from_ref(space, result[0]), w_input)
- assert api.PyUnicode_FSDecoder(None, result) == 1
+ assert PyUnicode_FSDecoder(space, None, result) == 1
# Converter
- ret = api.PyUnicode_FSConverter(w_input, result)
+ ret = PyUnicode_FSConverter(space, w_input, result)
assert ret == Py_CLEANUP_SUPPORTED
assert space.isinstance_w(from_ref(space, result[0]), space.w_bytes)
- assert api.PyUnicode_FSDecoder(None, result) == 1
+ assert PyUnicode_FSDecoder(space, None, result) == 1
- def test_IS(self, space, api):
+ def test_IS(self, space):
for char in [0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x85, 0xa0, 0x1680, 0x2000, 0x2001, 0x2002,
0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008,
0x2009, 0x200a,
#0x200b is in Other_Default_Ignorable_Code_Point in 4.1.0
0x2028, 0x2029, 0x202f, 0x205f, 0x3000]:
- assert api.Py_UNICODE_ISSPACE(unichr(char))
- assert not api.Py_UNICODE_ISSPACE(u'a')
+ assert Py_UNICODE_ISSPACE(space, unichr(char))
+ assert not Py_UNICODE_ISSPACE(space, u'a')
- assert api.Py_UNICODE_ISALPHA(u'a')
- assert not api.Py_UNICODE_ISALPHA(u'0')
- assert api.Py_UNICODE_ISALNUM(u'a')
- assert api.Py_UNICODE_ISALNUM(u'0')
- assert not api.Py_UNICODE_ISALNUM(u'+')
+ assert Py_UNICODE_ISALPHA(space, u'a')
+ assert not Py_UNICODE_ISALPHA(space, u'0')
+ assert Py_UNICODE_ISALNUM(space, u'a')
+ assert Py_UNICODE_ISALNUM(space, u'0')
+ assert not Py_UNICODE_ISALNUM(space, u'+')
- assert api.Py_UNICODE_ISDECIMAL(u'\u0660')
- assert not api.Py_UNICODE_ISDECIMAL(u'a')
- assert api.Py_UNICODE_ISDIGIT(u'9')
- assert not api.Py_UNICODE_ISDIGIT(u'@')
- assert api.Py_UNICODE_ISNUMERIC(u'9')
- assert not api.Py_UNICODE_ISNUMERIC(u'@')
+ assert Py_UNICODE_ISDECIMAL(space, u'\u0660')
+ assert not Py_UNICODE_ISDECIMAL(space, u'a')
+ assert Py_UNICODE_ISDIGIT(space, u'9')
+ assert not Py_UNICODE_ISDIGIT(space, u'@')
+ assert Py_UNICODE_ISNUMERIC(space, u'9')
+ assert not Py_UNICODE_ISNUMERIC(space, u'@')
for char in [0x0a, 0x0d, 0x1c, 0x1d, 0x1e, 0x85, 0x2028, 0x2029]:
- assert api.Py_UNICODE_ISLINEBREAK(unichr(char))
+ assert Py_UNICODE_ISLINEBREAK(space, unichr(char))
- assert api.Py_UNICODE_ISLOWER(u'\xdf') # sharp s
- assert api.Py_UNICODE_ISUPPER(u'\xde') # capital thorn
- assert api.Py_UNICODE_ISLOWER(u'a')
- assert not api.Py_UNICODE_ISUPPER(u'a')
- assert not api.Py_UNICODE_ISTITLE(u'\xce')
- assert api.Py_UNICODE_ISTITLE(
+ assert Py_UNICODE_ISLOWER(space, u'\xdf') # sharp s
More information about the pypy-commit
mailing list