[pypy-commit] pypy stm-gc: hg merge default
arigo
noreply at buildbot.pypy.org
Thu Feb 16 10:10:01 CET 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r52541:c98a02b2c23e
Date: 2012-02-16 09:22 +0100
http://bitbucket.org/pypy/pypy/changeset/c98a02b2c23e/
Log: hg merge default
diff --git a/lib_pypy/_subprocess.py b/lib_pypy/_subprocess.py
--- a/lib_pypy/_subprocess.py
+++ b/lib_pypy/_subprocess.py
@@ -87,7 +87,7 @@
# Now the _subprocess module implementation
-from ctypes import c_int as _c_int, byref as _byref
+from ctypes import c_int as _c_int, byref as _byref, WinError as _WinError
class _handle:
def __init__(self, handle):
@@ -116,7 +116,7 @@
res = _CreatePipe(_byref(read), _byref(write), None, size)
if not res:
- raise WindowsError("Error")
+ raise _WinError()
return _handle(read.value), _handle(write.value)
@@ -132,7 +132,7 @@
access, inherit, options)
if not res:
- raise WindowsError("Error")
+ raise _WinError()
return _handle(target.value)
DUPLICATE_SAME_ACCESS = 2
@@ -165,7 +165,7 @@
start_dir, _byref(si), _byref(pi))
if not res:
- raise WindowsError("Error")
+ raise _WinError()
return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessID, pi.dwThreadID
STARTF_USESHOWWINDOW = 0x001
@@ -178,7 +178,7 @@
res = _WaitForSingleObject(int(handle), milliseconds)
if res < 0:
- raise WindowsError("Error")
+ raise _WinError()
return res
INFINITE = 0xffffffff
@@ -190,7 +190,7 @@
res = _GetExitCodeProcess(int(handle), _byref(code))
if not res:
- raise WindowsError("Error")
+ raise _WinError()
return code.value
@@ -198,7 +198,7 @@
res = _TerminateProcess(int(handle), exitcode)
if not res:
- raise WindowsError("Error")
+ raise _WinError()
def GetStdHandle(stdhandle):
res = _GetStdHandle(stdhandle)
diff --git a/lib_pypy/ctypes_config_cache/pyexpat.ctc.py b/lib_pypy/ctypes_config_cache/pyexpat.ctc.py
deleted file mode 100644
--- a/lib_pypy/ctypes_config_cache/pyexpat.ctc.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""
-'ctypes_configure' source for pyexpat.py.
-Run this to rebuild _pyexpat_cache.py.
-"""
-
-import ctypes
-from ctypes import c_char_p, c_int, c_void_p, c_char
-from ctypes_configure import configure
-import dumpcache
-
-
-class CConfigure:
- _compilation_info_ = configure.ExternalCompilationInfo(
- includes = ['expat.h'],
- libraries = ['expat'],
- pre_include_lines = [
- '#define XML_COMBINED_VERSION (10000*XML_MAJOR_VERSION+100*XML_MINOR_VERSION+XML_MICRO_VERSION)'],
- )
-
- XML_Char = configure.SimpleType('XML_Char', c_char)
- XML_COMBINED_VERSION = configure.ConstantInteger('XML_COMBINED_VERSION')
- for name in ['XML_PARAM_ENTITY_PARSING_NEVER',
- 'XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE',
- 'XML_PARAM_ENTITY_PARSING_ALWAYS']:
- locals()[name] = configure.ConstantInteger(name)
-
- XML_Encoding = configure.Struct('XML_Encoding',[
- ('data', c_void_p),
- ('convert', c_void_p),
- ('release', c_void_p),
- ('map', c_int * 256)])
- XML_Content = configure.Struct('XML_Content',[
- ('numchildren', c_int),
- ('children', c_void_p),
- ('name', c_char_p),
- ('type', c_int),
- ('quant', c_int),
- ])
- # this is insanely stupid
- XML_FALSE = configure.ConstantInteger('XML_FALSE')
- XML_TRUE = configure.ConstantInteger('XML_TRUE')
-
-config = configure.configure(CConfigure)
-
-dumpcache.dumpcache2('pyexpat', config)
diff --git a/lib_pypy/ctypes_config_cache/test/test_cache.py b/lib_pypy/ctypes_config_cache/test/test_cache.py
--- a/lib_pypy/ctypes_config_cache/test/test_cache.py
+++ b/lib_pypy/ctypes_config_cache/test/test_cache.py
@@ -39,10 +39,6 @@
d = run('resource.ctc.py', '_resource_cache.py')
assert 'RLIM_NLIMITS' in d
-def test_pyexpat():
- d = run('pyexpat.ctc.py', '_pyexpat_cache.py')
- assert 'XML_COMBINED_VERSION' in d
-
def test_locale():
d = run('locale.ctc.py', '_locale_cache.py')
assert 'LC_ALL' in d
diff --git a/lib_pypy/datetime.py b/lib_pypy/datetime.py
--- a/lib_pypy/datetime.py
+++ b/lib_pypy/datetime.py
@@ -271,8 +271,9 @@
raise ValueError("%s()=%d, must be in -1439..1439" % (name, offset))
def _check_date_fields(year, month, day):
- if not isinstance(year, (int, long)):
- raise TypeError('int expected')
+ for value in [year, day]:
+ if not isinstance(value, (int, long)):
+ raise TypeError('int expected')
if not MINYEAR <= year <= MAXYEAR:
raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
if not 1 <= month <= 12:
@@ -282,8 +283,9 @@
raise ValueError('day must be in 1..%d' % dim, day)
def _check_time_fields(hour, minute, second, microsecond):
- if not isinstance(hour, (int, long)):
- raise TypeError('int expected')
+ for value in [hour, minute, second, microsecond]:
+ if not isinstance(value, (int, long)):
+ raise TypeError('int expected')
if not 0 <= hour <= 23:
raise ValueError('hour must be in 0..23', hour)
if not 0 <= minute <= 59:
diff --git a/lib_pypy/pyexpat.py b/lib_pypy/pyexpat.py
deleted file mode 100644
--- a/lib_pypy/pyexpat.py
+++ /dev/null
@@ -1,448 +0,0 @@
-
-import ctypes
-import ctypes.util
-from ctypes import c_char_p, c_int, c_void_p, POINTER, c_char, c_wchar_p
-import sys
-
-# load the platform-specific cache made by running pyexpat.ctc.py
-from ctypes_config_cache._pyexpat_cache import *
-
-try: from __pypy__ import builtinify
-except ImportError: builtinify = lambda f: f
-
-
-lib = ctypes.CDLL(ctypes.util.find_library('expat'))
-
-
-XML_Content.children = POINTER(XML_Content)
-XML_Parser = ctypes.c_void_p # an opaque pointer
-assert XML_Char is ctypes.c_char # this assumption is everywhere in
-# cpython's expat, let's explode
-
-def declare_external(name, args, res):
- func = getattr(lib, name)
- func.args = args
- func.restype = res
- globals()[name] = func
-
-declare_external('XML_ParserCreate', [c_char_p], XML_Parser)
-declare_external('XML_ParserCreateNS', [c_char_p, c_char], XML_Parser)
-declare_external('XML_Parse', [XML_Parser, c_char_p, c_int, c_int], c_int)
-currents = ['CurrentLineNumber', 'CurrentColumnNumber',
- 'CurrentByteIndex']
-for name in currents:
- func = getattr(lib, 'XML_Get' + name)
- func.args = [XML_Parser]
- func.restype = c_int
-
-declare_external('XML_SetReturnNSTriplet', [XML_Parser, c_int], None)
-declare_external('XML_GetSpecifiedAttributeCount', [XML_Parser], c_int)
-declare_external('XML_SetParamEntityParsing', [XML_Parser, c_int], None)
-declare_external('XML_GetErrorCode', [XML_Parser], c_int)
-declare_external('XML_StopParser', [XML_Parser, c_int], None)
-declare_external('XML_ErrorString', [c_int], c_char_p)
-declare_external('XML_SetBase', [XML_Parser, c_char_p], None)
-if XML_COMBINED_VERSION >= 19505:
- declare_external('XML_UseForeignDTD', [XML_Parser, c_int], None)
-
-declare_external('XML_SetUnknownEncodingHandler', [XML_Parser, c_void_p,
- c_void_p], None)
-declare_external('XML_FreeContentModel', [XML_Parser, POINTER(XML_Content)],
- None)
-declare_external('XML_ExternalEntityParserCreate', [XML_Parser,c_char_p,
- c_char_p],
- XML_Parser)
-
-handler_names = [
- 'StartElement',
- 'EndElement',
- 'ProcessingInstruction',
- 'CharacterData',
- 'UnparsedEntityDecl',
- 'NotationDecl',
- 'StartNamespaceDecl',
- 'EndNamespaceDecl',
- 'Comment',
- 'StartCdataSection',
- 'EndCdataSection',
- 'Default',
- 'DefaultHandlerExpand',
- 'NotStandalone',
- 'ExternalEntityRef',
- 'StartDoctypeDecl',
- 'EndDoctypeDecl',
- 'EntityDecl',
- 'XmlDecl',
- 'ElementDecl',
- 'AttlistDecl',
- ]
-if XML_COMBINED_VERSION >= 19504:
- handler_names.append('SkippedEntity')
-setters = {}
-
-for name in handler_names:
- if name == 'DefaultHandlerExpand':
- newname = 'XML_SetDefaultHandlerExpand'
- else:
- name += 'Handler'
- newname = 'XML_Set' + name
- cfunc = getattr(lib, newname)
- cfunc.args = [XML_Parser, ctypes.c_void_p]
- cfunc.result = ctypes.c_int
- setters[name] = cfunc
-
-class ExpatError(Exception):
- def __str__(self):
- return self.s
-
-error = ExpatError
-
-class XMLParserType(object):
- specified_attributes = 0
- ordered_attributes = 0
- returns_unicode = 1
- encoding = 'utf-8'
- def __init__(self, encoding, namespace_separator, _hook_external_entity=False):
- self.returns_unicode = 1
- if encoding:
- self.encoding = encoding
- if not _hook_external_entity:
- if namespace_separator is None:
- self.itself = XML_ParserCreate(encoding)
- else:
- self.itself = XML_ParserCreateNS(encoding, ord(namespace_separator))
- if not self.itself:
- raise RuntimeError("Creating parser failed")
- self._set_unknown_encoding_handler()
- self.storage = {}
- self.buffer = None
- self.buffer_size = 8192
- self.character_data_handler = None
- self.intern = {}
- self.__exc_info = None
-
- def _flush_character_buffer(self):
- if not self.buffer:
- return
- res = self._call_character_handler(''.join(self.buffer))
- self.buffer = []
- return res
-
- def _call_character_handler(self, buf):
- if self.character_data_handler:
- self.character_data_handler(buf)
-
- def _set_unknown_encoding_handler(self):
- def UnknownEncoding(encodingData, name, info_p):
- info = info_p.contents
- s = ''.join([chr(i) for i in range(256)])
- u = s.decode(self.encoding, 'replace')
- for i in range(len(u)):
- if u[i] == u'\xfffd':
- info.map[i] = -1
- else:
- info.map[i] = ord(u[i])
- info.data = None
- info.convert = None
- info.release = None
- return 1
-
- CB = ctypes.CFUNCTYPE(c_int, c_void_p, c_char_p, POINTER(XML_Encoding))
- cb = CB(UnknownEncoding)
- self._unknown_encoding_handler = (cb, UnknownEncoding)
- XML_SetUnknownEncodingHandler(self.itself, cb, None)
-
- def _set_error(self, code):
- e = ExpatError()
- e.code = code
- lineno = lib.XML_GetCurrentLineNumber(self.itself)
- colno = lib.XML_GetCurrentColumnNumber(self.itself)
- e.offset = colno
- e.lineno = lineno
- err = XML_ErrorString(code)[:200]
- e.s = "%s: line: %d, column: %d" % (err, lineno, colno)
- e.message = e.s
- self._error = e
-
- def Parse(self, data, is_final=0):
- res = XML_Parse(self.itself, data, len(data), is_final)
- if res == 0:
- self._set_error(XML_GetErrorCode(self.itself))
- if self.__exc_info:
- exc_info = self.__exc_info
- self.__exc_info = None
- raise exc_info[0], exc_info[1], exc_info[2]
- else:
- raise self._error
- self._flush_character_buffer()
- return res
-
- def _sethandler(self, name, real_cb):
- setter = setters[name]
- try:
- cb = self.storage[(name, real_cb)]
- except KeyError:
- cb = getattr(self, 'get_cb_for_%s' % name)(real_cb)
- self.storage[(name, real_cb)] = cb
- except TypeError:
- # weellll...
- cb = getattr(self, 'get_cb_for_%s' % name)(real_cb)
- setter(self.itself, cb)
-
- def _wrap_cb(self, cb):
- def f(*args):
- try:
- return cb(*args)
- except:
- self.__exc_info = sys.exc_info()
- XML_StopParser(self.itself, XML_FALSE)
- return f
-
- def get_cb_for_StartElementHandler(self, real_cb):
- def StartElement(unused, name, attrs):
- # unpack name and attrs
- conv = self.conv
- self._flush_character_buffer()
- if self.specified_attributes:
- max = XML_GetSpecifiedAttributeCount(self.itself)
- else:
- max = 0
- while attrs[max]:
- max += 2 # copied
- if self.ordered_attributes:
- res = [attrs[i] for i in range(max)]
- else:
- res = {}
- for i in range(0, max, 2):
- res[conv(attrs[i])] = conv(attrs[i + 1])
- real_cb(conv(name), res)
- StartElement = self._wrap_cb(StartElement)
- CB = ctypes.CFUNCTYPE(None, c_void_p, c_char_p, POINTER(c_char_p))
- return CB(StartElement)
-
- def get_cb_for_ExternalEntityRefHandler(self, real_cb):
- def ExternalEntity(unused, context, base, sysId, pubId):
- self._flush_character_buffer()
- conv = self.conv
- res = real_cb(conv(context), conv(base), conv(sysId),
- conv(pubId))
- if res is None:
- return 0
- return res
- ExternalEntity = self._wrap_cb(ExternalEntity)
- CB = ctypes.CFUNCTYPE(c_int, c_void_p, *([c_char_p] * 4))
- return CB(ExternalEntity)
-
- def get_cb_for_CharacterDataHandler(self, real_cb):
- def CharacterData(unused, s, lgt):
- if self.buffer is None:
- self._call_character_handler(self.conv(s[:lgt]))
- else:
- if len(self.buffer) + lgt > self.buffer_size:
- self._flush_character_buffer()
- if self.character_data_handler is None:
- return
- if lgt >= self.buffer_size:
- self._call_character_handler(s[:lgt])
- self.buffer = []
- else:
- self.buffer.append(s[:lgt])
- CharacterData = self._wrap_cb(CharacterData)
- CB = ctypes.CFUNCTYPE(None, c_void_p, POINTER(c_char), c_int)
- return CB(CharacterData)
-
- def get_cb_for_NotStandaloneHandler(self, real_cb):
- def NotStandaloneHandler(unused):
- return real_cb()
- NotStandaloneHandler = self._wrap_cb(NotStandaloneHandler)
- CB = ctypes.CFUNCTYPE(c_int, c_void_p)
- return CB(NotStandaloneHandler)
-
- def get_cb_for_EntityDeclHandler(self, real_cb):
- def EntityDecl(unused, ename, is_param, value, value_len, base,
- system_id, pub_id, not_name):
- self._flush_character_buffer()
- if not value:
- value = None
- else:
- value = value[:value_len]
- args = [ename, is_param, value, base, system_id,
- pub_id, not_name]
- args = [self.conv(arg) for arg in args]
- real_cb(*args)
- EntityDecl = self._wrap_cb(EntityDecl)
- CB = ctypes.CFUNCTYPE(None, c_void_p, c_char_p, c_int, c_char_p,
- c_int, c_char_p, c_char_p, c_char_p, c_char_p)
- return CB(EntityDecl)
-
- def _conv_content_model(self, model):
- children = tuple([self._conv_content_model(model.children[i])
- for i in range(model.numchildren)])
- return (model.type, model.quant, self.conv(model.name),
- children)
-
- def get_cb_for_ElementDeclHandler(self, real_cb):
- def ElementDecl(unused, name, model):
- self._flush_character_buffer()
- modelobj = self._conv_content_model(model[0])
- real_cb(name, modelobj)
- XML_FreeContentModel(self.itself, model)
-
- ElementDecl = self._wrap_cb(ElementDecl)
- CB = ctypes.CFUNCTYPE(None, c_void_p, c_char_p, POINTER(XML_Content))
- return CB(ElementDecl)
-
- def _new_callback_for_string_len(name, sign):
- def get_callback_for_(self, real_cb):
- def func(unused, s, len):
- self._flush_character_buffer()
- arg = self.conv(s[:len])
- real_cb(arg)
- func.func_name = name
- func = self._wrap_cb(func)
- CB = ctypes.CFUNCTYPE(*sign)
- return CB(func)
- get_callback_for_.func_name = 'get_cb_for_' + name
- return get_callback_for_
-
- for name in ['DefaultHandlerExpand',
- 'DefaultHandler']:
- sign = [None, c_void_p, POINTER(c_char), c_int]
- name = 'get_cb_for_' + name
- locals()[name] = _new_callback_for_string_len(name, sign)
-
- def _new_callback_for_starargs(name, sign):
- def get_callback_for_(self, real_cb):
- def func(unused, *args):
- self._flush_character_buffer()
- args = [self.conv(arg) for arg in args]
- real_cb(*args)
- func.func_name = name
- func = self._wrap_cb(func)
- CB = ctypes.CFUNCTYPE(*sign)
- return CB(func)
- get_callback_for_.func_name = 'get_cb_for_' + name
- return get_callback_for_
-
- for name, num_or_sign in [
- ('EndElementHandler', 1),
- ('ProcessingInstructionHandler', 2),
- ('UnparsedEntityDeclHandler', 5),
- ('NotationDeclHandler', 4),
- ('StartNamespaceDeclHandler', 2),
- ('EndNamespaceDeclHandler', 1),
- ('CommentHandler', 1),
- ('StartCdataSectionHandler', 0),
- ('EndCdataSectionHandler', 0),
- ('StartDoctypeDeclHandler', [None, c_void_p] + [c_char_p] * 3 + [c_int]),
- ('XmlDeclHandler', [None, c_void_p, c_char_p, c_char_p, c_int]),
- ('AttlistDeclHandler', [None, c_void_p] + [c_char_p] * 4 + [c_int]),
- ('EndDoctypeDeclHandler', 0),
- ('SkippedEntityHandler', [None, c_void_p, c_char_p, c_int]),
- ]:
- if isinstance(num_or_sign, int):
- sign = [None, c_void_p] + [c_char_p] * num_or_sign
- else:
- sign = num_or_sign
- name = 'get_cb_for_' + name
- locals()[name] = _new_callback_for_starargs(name, sign)
-
- def conv_unicode(self, s):
- if s is None or isinstance(s, int):
- return s
- return s.decode(self.encoding, "strict")
-
- def __setattr__(self, name, value):
- # forest of ifs...
- if name in ['ordered_attributes',
- 'returns_unicode', 'specified_attributes']:
- if value:
- if name == 'returns_unicode':
- self.conv = self.conv_unicode
- self.__dict__[name] = 1
- else:
- if name == 'returns_unicode':
- self.conv = lambda s: s
- self.__dict__[name] = 0
- elif name == 'buffer_text':
- if value:
- self.buffer = []
- else:
- self._flush_character_buffer()
- self.buffer = None
- elif name == 'buffer_size':
- if not isinstance(value, int):
- raise TypeError("Expected int")
- if value <= 0:
- raise ValueError("Expected positive int")
- self.__dict__[name] = value
- elif name == 'namespace_prefixes':
- XML_SetReturnNSTriplet(self.itself, int(bool(value)))
- elif name in setters:
- if name == 'CharacterDataHandler':
- # XXX we need to flush buffer here
- self._flush_character_buffer()
- self.character_data_handler = value
- #print name
- #print value
- #print
- self._sethandler(name, value)
- else:
- self.__dict__[name] = value
-
- def SetParamEntityParsing(self, arg):
- XML_SetParamEntityParsing(self.itself, arg)
-
- if XML_COMBINED_VERSION >= 19505:
- def UseForeignDTD(self, arg=True):
- if arg:
- flag = XML_TRUE
- else:
- flag = XML_FALSE
- XML_UseForeignDTD(self.itself, flag)
-
- def __getattr__(self, name):
- if name == 'buffer_text':
- return self.buffer is not None
- elif name in currents:
- return getattr(lib, 'XML_Get' + name)(self.itself)
- elif name == 'ErrorColumnNumber':
- return lib.XML_GetCurrentColumnNumber(self.itself)
- elif name == 'ErrorLineNumber':
- return lib.XML_GetCurrentLineNumber(self.itself)
- return self.__dict__[name]
-
- def ParseFile(self, file):
- return self.Parse(file.read(), False)
-
- def SetBase(self, base):
- XML_SetBase(self.itself, base)
-
- def ExternalEntityParserCreate(self, context, encoding=None):
- """ExternalEntityParserCreate(context[, encoding])
- Create a parser for parsing an external entity based on the
- information passed to the ExternalEntityRefHandler."""
- new_parser = XMLParserType(encoding, None, True)
- new_parser.itself = XML_ExternalEntityParserCreate(self.itself,
- context, encoding)
- new_parser._set_unknown_encoding_handler()
- return new_parser
-
- at builtinify
-def ErrorString(errno):
- return XML_ErrorString(errno)[:200]
-
- at builtinify
-def ParserCreate(encoding=None, namespace_separator=None, intern=None):
- if (not isinstance(encoding, str) and
- not encoding is None):
- raise TypeError("ParserCreate() argument 1 must be string or None, not %s" % encoding.__class__.__name__)
- if (not isinstance(namespace_separator, str) and
- not namespace_separator is None):
- raise TypeError("ParserCreate() argument 2 must be string or None, not %s" % namespace_separator.__class__.__name__)
- if namespace_separator is not None:
- if len(namespace_separator) > 1:
- raise ValueError('namespace_separator must be at most one character, omitted, or None')
- if len(namespace_separator) == 0:
- namespace_separator = None
- return XMLParserType(encoding, namespace_separator)
diff --git a/lib_pypy/pypy_test/test_pyexpat.py b/lib_pypy/pypy_test/test_pyexpat.py
deleted file mode 100644
--- a/lib_pypy/pypy_test/test_pyexpat.py
+++ /dev/null
@@ -1,665 +0,0 @@
-# XXX TypeErrors on calling handlers, or on bad return values from a
-# handler, are obscure and unhelpful.
-
-from __future__ import absolute_import
-import StringIO, sys
-import unittest, py
-
-from lib_pypy.ctypes_config_cache import rebuild
-rebuild.rebuild_one('pyexpat.ctc.py')
-
-from lib_pypy import pyexpat
-#from xml.parsers import expat
-expat = pyexpat
-
-from test.test_support import sortdict, run_unittest
-
-
-class TestSetAttribute:
- def setup_method(self, meth):
- self.parser = expat.ParserCreate(namespace_separator='!')
- self.set_get_pairs = [
- [0, 0],
- [1, 1],
- [2, 1],
- [0, 0],
- ]
-
- def test_returns_unicode(self):
- for x, y in self.set_get_pairs:
- self.parser.returns_unicode = x
- assert self.parser.returns_unicode == y
-
- def test_ordered_attributes(self):
- for x, y in self.set_get_pairs:
- self.parser.ordered_attributes = x
- assert self.parser.ordered_attributes == y
-
- def test_specified_attributes(self):
- for x, y in self.set_get_pairs:
- self.parser.specified_attributes = x
- assert self.parser.specified_attributes == y
-
-
-data = '''\
-<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
-<?xml-stylesheet href="stylesheet.css"?>
-<!-- comment data -->
-<!DOCTYPE quotations SYSTEM "quotations.dtd" [
-<!ELEMENT root ANY>
-<!ATTLIST root attr1 CDATA #REQUIRED attr2 CDATA #IMPLIED>
-<!NOTATION notation SYSTEM "notation.jpeg">
-<!ENTITY acirc "â">
-<!ENTITY external_entity SYSTEM "entity.file">
-<!ENTITY unparsed_entity SYSTEM "entity.file" NDATA notation>
-%unparsed_entity;
-]>
-
-<root attr1="value1" attr2="value2ὀ">
-<myns:subelement xmlns:myns="http://www.python.org/namespace">
- Contents of subelements
-</myns:subelement>
-<sub2><![CDATA[contents of CDATA section]]></sub2>
-&external_entity;
-&skipped_entity;
-</root>
-'''
-
-
-# Produce UTF-8 output
-class TestParse:
- class Outputter:
- def __init__(self):
- self.out = []
-
- def StartElementHandler(self, name, attrs):
- self.out.append('Start element: ' + repr(name) + ' ' +
- sortdict(attrs))
-
- def EndElementHandler(self, name):
- self.out.append('End element: ' + repr(name))
-
- def CharacterDataHandler(self, data):
- data = data.strip()
- if data:
- self.out.append('Character data: ' + repr(data))
-
- def ProcessingInstructionHandler(self, target, data):
- self.out.append('PI: ' + repr(target) + ' ' + repr(data))
-
- def StartNamespaceDeclHandler(self, prefix, uri):
- self.out.append('NS decl: ' + repr(prefix) + ' ' + repr(uri))
-
- def EndNamespaceDeclHandler(self, prefix):
- self.out.append('End of NS decl: ' + repr(prefix))
-
- def StartCdataSectionHandler(self):
- self.out.append('Start of CDATA section')
-
- def EndCdataSectionHandler(self):
- self.out.append('End of CDATA section')
-
- def CommentHandler(self, text):
- self.out.append('Comment: ' + repr(text))
-
- def NotationDeclHandler(self, *args):
- name, base, sysid, pubid = args
- self.out.append('Notation declared: %s' %(args,))
-
- def UnparsedEntityDeclHandler(self, *args):
- entityName, base, systemId, publicId, notationName = args
- self.out.append('Unparsed entity decl: %s' %(args,))
-
- def NotStandaloneHandler(self):
- self.out.append('Not standalone')
- return 1
-
- def ExternalEntityRefHandler(self, *args):
- context, base, sysId, pubId = args
- self.out.append('External entity ref: %s' %(args[1:],))
- return 1
-
- def StartDoctypeDeclHandler(self, *args):
- self.out.append(('Start doctype', args))
- return 1
-
- def EndDoctypeDeclHandler(self):
- self.out.append("End doctype")
- return 1
-
- def EntityDeclHandler(self, *args):
- self.out.append(('Entity declaration', args))
- return 1
-
- def XmlDeclHandler(self, *args):
- self.out.append(('XML declaration', args))
- return 1
-
- def ElementDeclHandler(self, *args):
- self.out.append(('Element declaration', args))
- return 1
-
- def AttlistDeclHandler(self, *args):
- self.out.append(('Attribute list declaration', args))
- return 1
-
- def SkippedEntityHandler(self, *args):
- self.out.append(("Skipped entity", args))
- return 1
-
- def DefaultHandler(self, userData):
- pass
-
- def DefaultHandlerExpand(self, userData):
- pass
-
- handler_names = [
- 'StartElementHandler', 'EndElementHandler', 'CharacterDataHandler',
- 'ProcessingInstructionHandler', 'UnparsedEntityDeclHandler',
- 'NotationDeclHandler', 'StartNamespaceDeclHandler',
- 'EndNamespaceDeclHandler', 'CommentHandler',
- 'StartCdataSectionHandler', 'EndCdataSectionHandler', 'DefaultHandler',
- 'DefaultHandlerExpand', 'NotStandaloneHandler',
- 'ExternalEntityRefHandler', 'StartDoctypeDeclHandler',
- 'EndDoctypeDeclHandler', 'EntityDeclHandler', 'XmlDeclHandler',
- 'ElementDeclHandler', 'AttlistDeclHandler', 'SkippedEntityHandler',
- ]
-
- def test_utf8(self):
-
- out = self.Outputter()
- parser = expat.ParserCreate(namespace_separator='!')
- for name in self.handler_names:
- setattr(parser, name, getattr(out, name))
- parser.returns_unicode = 0
- parser.Parse(data, 1)
-
- # Verify output
- operations = out.out
- expected_operations = [
- ('XML declaration', (u'1.0', u'iso-8859-1', 0)),
- 'PI: \'xml-stylesheet\' \'href="stylesheet.css"\'',
- "Comment: ' comment data '",
- "Not standalone",
- ("Start doctype", ('quotations', 'quotations.dtd', None, 1)),
- ('Element declaration', (u'root', (2, 0, None, ()))),
- ('Attribute list declaration', ('root', 'attr1', 'CDATA', None,
- 1)),
- ('Attribute list declaration', ('root', 'attr2', 'CDATA', None,
- 0)),
- "Notation declared: ('notation', None, 'notation.jpeg', None)",
- ('Entity declaration', ('acirc', 0, '\xc3\xa2', None, None, None, None)),
- ('Entity declaration', ('external_entity', 0, None, None,
- 'entity.file', None, None)),
- "Unparsed entity decl: ('unparsed_entity', None, 'entity.file', None, 'notation')",
- "Not standalone",
- "End doctype",
- "Start element: 'root' {'attr1': 'value1', 'attr2': 'value2\\xe1\\xbd\\x80'}",
- "NS decl: 'myns' 'http://www.python.org/namespace'",
- "Start element: 'http://www.python.org/namespace!subelement' {}",
- "Character data: 'Contents of subelements'",
- "End element: 'http://www.python.org/namespace!subelement'",
- "End of NS decl: 'myns'",
- "Start element: 'sub2' {}",
- 'Start of CDATA section',
- "Character data: 'contents of CDATA section'",
- 'End of CDATA section',
- "End element: 'sub2'",
- "External entity ref: (None, 'entity.file', None)",
- ('Skipped entity', ('skipped_entity', 0)),
- "End element: 'root'",
- ]
- for operation, expected_operation in zip(operations, expected_operations):
- assert operation == expected_operation
-
- def test_unicode(self):
- # Try the parse again, this time producing Unicode output
- out = self.Outputter()
- parser = expat.ParserCreate(namespace_separator='!')
- parser.returns_unicode = 1
- for name in self.handler_names:
- setattr(parser, name, getattr(out, name))
-
- parser.Parse(data, 1)
-
- operations = out.out
- expected_operations = [
- ('XML declaration', (u'1.0', u'iso-8859-1', 0)),
- 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'',
- "Comment: u' comment data '",
- "Not standalone",
- ("Start doctype", ('quotations', 'quotations.dtd', None, 1)),
- ('Element declaration', (u'root', (2, 0, None, ()))),
- ('Attribute list declaration', ('root', 'attr1', 'CDATA', None,
- 1)),
- ('Attribute list declaration', ('root', 'attr2', 'CDATA', None,
- 0)),
- "Notation declared: (u'notation', None, u'notation.jpeg', None)",
- ('Entity declaration', (u'acirc', 0, u'\xe2', None, None, None,
- None)),
- ('Entity declaration', (u'external_entity', 0, None, None,
- u'entity.file', None, None)),
- "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')",
- "Not standalone",
- "End doctype",
- "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}",
- "NS decl: u'myns' u'http://www.python.org/namespace'",
- "Start element: u'http://www.python.org/namespace!subelement' {}",
- "Character data: u'Contents of subelements'",
- "End element: u'http://www.python.org/namespace!subelement'",
- "End of NS decl: u'myns'",
- "Start element: u'sub2' {}",
- 'Start of CDATA section',
- "Character data: u'contents of CDATA section'",
- 'End of CDATA section',
- "End element: u'sub2'",
- "External entity ref: (None, u'entity.file', None)",
- ('Skipped entity', ('skipped_entity', 0)),
- "End element: u'root'",
- ]
- for operation, expected_operation in zip(operations, expected_operations):
- assert operation == expected_operation
-
- def test_parse_file(self):
- # Try parsing a file
- out = self.Outputter()
- parser = expat.ParserCreate(namespace_separator='!')
- parser.returns_unicode = 1
- for name in self.handler_names:
- setattr(parser, name, getattr(out, name))
- file = StringIO.StringIO(data)
-
- parser.ParseFile(file)
-
- operations = out.out
- expected_operations = [
- ('XML declaration', (u'1.0', u'iso-8859-1', 0)),
- 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'',
- "Comment: u' comment data '",
- "Not standalone",
- ("Start doctype", ('quotations', 'quotations.dtd', None, 1)),
- ('Element declaration', (u'root', (2, 0, None, ()))),
- ('Attribute list declaration', ('root', 'attr1', 'CDATA', None,
- 1)),
- ('Attribute list declaration', ('root', 'attr2', 'CDATA', None,
- 0)),
- "Notation declared: (u'notation', None, u'notation.jpeg', None)",
- ('Entity declaration', ('acirc', 0, u'\xe2', None, None, None, None)),
- ('Entity declaration', (u'external_entity', 0, None, None, u'entity.file', None, None)),
- "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')",
- "Not standalone",
- "End doctype",
- "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}",
- "NS decl: u'myns' u'http://www.python.org/namespace'",
- "Start element: u'http://www.python.org/namespace!subelement' {}",
- "Character data: u'Contents of subelements'",
- "End element: u'http://www.python.org/namespace!subelement'",
- "End of NS decl: u'myns'",
- "Start element: u'sub2' {}",
- 'Start of CDATA section',
- "Character data: u'contents of CDATA section'",
- 'End of CDATA section',
- "End element: u'sub2'",
- "External entity ref: (None, u'entity.file', None)",
- ('Skipped entity', ('skipped_entity', 0)),
- "End element: u'root'",
- ]
- for operation, expected_operation in zip(operations, expected_operations):
- assert operation == expected_operation
-
-
-class TestNamespaceSeparator:
- def test_legal(self):
- # Tests that make sure we get errors when the namespace_separator value
- # is illegal, and that we don't for good values:
- expat.ParserCreate()
- expat.ParserCreate(namespace_separator=None)
- expat.ParserCreate(namespace_separator=' ')
-
- def test_illegal(self):
- try:
- expat.ParserCreate(namespace_separator=42)
- raise AssertionError
- except TypeError, e:
- assert str(e) == (
- 'ParserCreate() argument 2 must be string or None, not int')
-
- try:
- expat.ParserCreate(namespace_separator='too long')
- raise AssertionError
- except ValueError, e:
- assert str(e) == (
- 'namespace_separator must be at most one character, omitted, or None')
-
- def test_zero_length(self):
- # ParserCreate() needs to accept a namespace_separator of zero length
- # to satisfy the requirements of RDF applications that are required
- # to simply glue together the namespace URI and the localname. Though
- # considered a wart of the RDF specifications, it needs to be supported.
- #
- # See XML-SIG mailing list thread starting with
- # http://mail.python.org/pipermail/xml-sig/2001-April/005202.html
- #
- expat.ParserCreate(namespace_separator='') # too short
-
-
-class TestInterning:
- def test(self):
- py.test.skip("Not working")
- # Test the interning machinery.
- p = expat.ParserCreate()
- L = []
- def collector(name, *args):
- L.append(name)
- p.StartElementHandler = collector
- p.EndElementHandler = collector
- p.Parse("<e> <e/> <e></e> </e>", 1)
- tag = L[0]
- assert len(L) == 6
- for entry in L:
- # L should have the same string repeated over and over.
- assert tag is entry
-
-
-class TestBufferText:
- def setup_method(self, meth):
- self.stuff = []
- self.parser = expat.ParserCreate()
- self.parser.buffer_text = 1
- self.parser.CharacterDataHandler = self.CharacterDataHandler
-
- def check(self, expected, label):
- assert self.stuff == expected, (
- "%s\nstuff = %r\nexpected = %r"
- % (label, self.stuff, map(unicode, expected)))
-
- def CharacterDataHandler(self, text):
- self.stuff.append(text)
-
- def StartElementHandler(self, name, attrs):
- self.stuff.append("<%s>" % name)
- bt = attrs.get("buffer-text")
- if bt == "yes":
- self.parser.buffer_text = 1
- elif bt == "no":
- self.parser.buffer_text = 0
-
- def EndElementHandler(self, name):
- self.stuff.append("</%s>" % name)
-
- def CommentHandler(self, data):
- self.stuff.append("<!--%s-->" % data)
-
- def setHandlers(self, handlers=[]):
- for name in handlers:
- setattr(self.parser, name, getattr(self, name))
-
- def test_default_to_disabled(self):
- parser = expat.ParserCreate()
- assert not parser.buffer_text
-
- def test_buffering_enabled(self):
- # Make sure buffering is turned on
- assert self.parser.buffer_text
- self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
- assert self.stuff == ['123'], (
- "buffered text not properly collapsed")
-
- def test1(self):
- # XXX This test exposes more detail of Expat's text chunking than we
- # XXX like, but it tests what we need to concisely.
- self.setHandlers(["StartElementHandler"])
- self.parser.Parse("<a>1<b buffer-text='no'/>2\n3<c buffer-text='yes'/>4\n5</a>", 1)
- assert self.stuff == (
- ["<a>", "1", "<b>", "2", "\n", "3", "<c>", "4\n5"]), (
- "buffering control not reacting as expected")
-
- def test2(self):
- self.parser.Parse("<a>1<b/><2><c/> \n 3</a>", 1)
- assert self.stuff == ["1<2> \n 3"], (
- "buffered text not properly collapsed")
-
- def test3(self):
- self.setHandlers(["StartElementHandler"])
- self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
- assert self.stuff == ["<a>", "1", "<b>", "2", "<c>", "3"], (
- "buffered text not properly split")
-
- def test4(self):
- self.setHandlers(["StartElementHandler", "EndElementHandler"])
- self.parser.CharacterDataHandler = None
- self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
- assert self.stuff == (
- ["<a>", "<b>", "</b>", "<c>", "</c>", "</a>"])
-
- def test5(self):
- self.setHandlers(["StartElementHandler", "EndElementHandler"])
- self.parser.Parse("<a>1<b></b>2<c/>3</a>", 1)
- assert self.stuff == (
- ["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3", "</a>"])
-
- def test6(self):
- self.setHandlers(["CommentHandler", "EndElementHandler",
- "StartElementHandler"])
- self.parser.Parse("<a>1<b/>2<c></c>345</a> ", 1)
- assert self.stuff == (
- ["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "345", "</a>"]), (
- "buffered text not properly split")
-
- def test7(self):
- self.setHandlers(["CommentHandler", "EndElementHandler",
- "StartElementHandler"])
- self.parser.Parse("<a>1<b/>2<c></c>3<!--abc-->4<!--def-->5</a> ", 1)
- assert self.stuff == (
- ["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3",
- "<!--abc-->", "4", "<!--def-->", "5", "</a>"]), (
- "buffered text not properly split")
-
-
-# Test handling of exception from callback:
-class TestHandlerException:
- def StartElementHandler(self, name, attrs):
- raise RuntimeError(name)
-
- def test(self):
- parser = expat.ParserCreate()
- parser.StartElementHandler = self.StartElementHandler
- try:
- parser.Parse("<a><b><c/></b></a>", 1)
- raise AssertionError
- except RuntimeError, e:
- assert e.args[0] == 'a', (
- "Expected RuntimeError for element 'a', but" + \
- " found %r" % e.args[0])
-
-
-# Test Current* members:
-class TestPosition:
- def StartElementHandler(self, name, attrs):
- self.check_pos('s')
-
- def EndElementHandler(self, name):
- self.check_pos('e')
-
- def check_pos(self, event):
- pos = (event,
- self.parser.CurrentByteIndex,
- self.parser.CurrentLineNumber,
- self.parser.CurrentColumnNumber)
- assert self.upto < len(self.expected_list)
- expected = self.expected_list[self.upto]
- assert pos == expected, (
- 'Expected position %s, got position %s' %(pos, expected))
- self.upto += 1
-
- def test(self):
- self.parser = expat.ParserCreate()
- self.parser.StartElementHandler = self.StartElementHandler
- self.parser.EndElementHandler = self.EndElementHandler
- self.upto = 0
- self.expected_list = [('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2),
- ('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)]
-
- xml = '<a>\n <b>\n <c/>\n </b>\n</a>'
- self.parser.Parse(xml, 1)
-
-
-class Testsf1296433:
- def test_parse_only_xml_data(self):
- # http://python.org/sf/1296433
- #
- xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * 1025)
- # this one doesn't crash
- #xml = "<?xml version='1.0'?><s>%s</s>" % ('a' * 10000)
-
- class SpecificException(Exception):
- pass
-
- def handler(text):
- raise SpecificException
-
- parser = expat.ParserCreate()
- parser.CharacterDataHandler = handler
-
- py.test.raises(Exception, parser.Parse, xml)
-
-class TestChardataBuffer:
- """
- test setting of chardata buffer size
- """
-
- def test_1025_bytes(self):
- assert self.small_buffer_test(1025) == 2
-
- def test_1000_bytes(self):
- assert self.small_buffer_test(1000) == 1
-
- def test_wrong_size(self):
- parser = expat.ParserCreate()
- parser.buffer_text = 1
- def f(size):
- parser.buffer_size = size
-
- py.test.raises(TypeError, f, sys.maxint+1)
- py.test.raises(ValueError, f, -1)
- py.test.raises(ValueError, f, 0)
-
- def test_unchanged_size(self):
- xml1 = ("<?xml version='1.0' encoding='iso8859'?><s>%s" % ('a' * 512))
- xml2 = 'a'*512 + '</s>'
- parser = expat.ParserCreate()
- parser.CharacterDataHandler = self.counting_handler
- parser.buffer_size = 512
- parser.buffer_text = 1
-
- # Feed 512 bytes of character data: the handler should be called
- # once.
- self.n = 0
- parser.Parse(xml1)
- assert self.n == 1
-
- # Reassign to buffer_size, but assign the same size.
- parser.buffer_size = parser.buffer_size
- assert self.n == 1
-
- # Try parsing rest of the document
- parser.Parse(xml2)
- assert self.n == 2
-
-
- def test_disabling_buffer(self):
- xml1 = "<?xml version='1.0' encoding='iso8859'?><a>%s" % ('a' * 512)
- xml2 = ('b' * 1024)
- xml3 = "%s</a>" % ('c' * 1024)
- parser = expat.ParserCreate()
- parser.CharacterDataHandler = self.counting_handler
- parser.buffer_text = 1
- parser.buffer_size = 1024
- assert parser.buffer_size == 1024
-
- # Parse one chunk of XML
- self.n = 0
- parser.Parse(xml1, 0)
- assert parser.buffer_size == 1024
- assert self.n == 1
-
- # Turn off buffering and parse the next chunk.
- parser.buffer_text = 0
- assert not parser.buffer_text
- assert parser.buffer_size == 1024
- for i in range(10):
- parser.Parse(xml2, 0)
- assert self.n == 11
-
- parser.buffer_text = 1
- assert parser.buffer_text
- assert parser.buffer_size == 1024
- parser.Parse(xml3, 1)
- assert self.n == 12
-
-
-
- def make_document(self, bytes):
- return ("<?xml version='1.0'?><tag>" + bytes * 'a' + '</tag>')
-
- def counting_handler(self, text):
- self.n += 1
-
- def small_buffer_test(self, buffer_len):
- xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * buffer_len)
- parser = expat.ParserCreate()
- parser.CharacterDataHandler = self.counting_handler
- parser.buffer_size = 1024
- parser.buffer_text = 1
-
- self.n = 0
- parser.Parse(xml)
- return self.n
-
- def test_change_size_1(self):
- xml1 = "<?xml version='1.0' encoding='iso8859'?><a><s>%s" % ('a' * 1024)
- xml2 = "aaa</s><s>%s</s></a>" % ('a' * 1025)
- parser = expat.ParserCreate()
- parser.CharacterDataHandler = self.counting_handler
- parser.buffer_text = 1
- parser.buffer_size = 1024
- assert parser.buffer_size == 1024
-
- self.n = 0
- parser.Parse(xml1, 0)
- parser.buffer_size *= 2
- assert parser.buffer_size == 2048
- parser.Parse(xml2, 1)
- assert self.n == 2
-
- def test_change_size_2(self):
- xml1 = "<?xml version='1.0' encoding='iso8859'?><a>a<s>%s" % ('a' * 1023)
- xml2 = "aaa</s><s>%s</s></a>" % ('a' * 1025)
- parser = expat.ParserCreate()
- parser.CharacterDataHandler = self.counting_handler
- parser.buffer_text = 1
- parser.buffer_size = 2048
- assert parser.buffer_size == 2048
-
- self.n=0
- parser.Parse(xml1, 0)
- parser.buffer_size /= 2
- assert parser.buffer_size == 1024
- parser.Parse(xml2, 1)
- assert self.n == 4
-
- def test_segfault(self):
- py.test.raises(TypeError, expat.ParserCreate, 1234123123)
-
-def test_invalid_data():
- parser = expat.ParserCreate()
- parser.Parse('invalid.xml', 0)
- try:
- parser.Parse("", 1)
- except expat.ExpatError, e:
- assert e.code == 2 # XXX is this reliable?
- assert e.lineno == 1
- assert e.message.startswith('syntax error')
- else:
- py.test.fail("Did not raise")
-
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -111,7 +111,8 @@
BoolOption("sandbox", "Produce a fully-sandboxed executable",
default=False, cmdline="--sandbox",
requires=[("translation.thread", False)],
- suggests=[("translation.gc", "generation")]),
+ suggests=[("translation.gc", "generation"),
+ ("translation.gcrootfinder", "shadowstack")]),
BoolOption("rweakref", "The backend supports RPython-level weakrefs",
default=True),
diff --git a/pypy/doc/coding-guide.rst b/pypy/doc/coding-guide.rst
--- a/pypy/doc/coding-guide.rst
+++ b/pypy/doc/coding-guide.rst
@@ -388,7 +388,9 @@
In a few cases (e.g. hash table manipulation), we need machine-sized unsigned
arithmetic. For these cases there is the r_uint class, which is a pure
Python implementation of word-sized unsigned integers that silently wrap
- around. The purpose of this class (as opposed to helper functions as above)
+ around. ("word-sized" and "machine-sized" are used equivalently and mean
+ the native size, which you get using "unsigned long" in C.)
+ The purpose of this class (as opposed to helper functions as above)
is consistent typing: both Python and the annotator will propagate r_uint
instances in the program and interpret all the operations between them as
unsigned. Instances of r_uint are special-cased by the code generators to
diff --git a/pypy/doc/config/objspace.usemodules.pyexpat.txt b/pypy/doc/config/objspace.usemodules.pyexpat.txt
--- a/pypy/doc/config/objspace.usemodules.pyexpat.txt
+++ b/pypy/doc/config/objspace.usemodules.pyexpat.txt
@@ -1,2 +1,1 @@
-Use (experimental) pyexpat module written in RPython, instead of CTypes
-version which is used by default.
+Use the pyexpat module, written in RPython.
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -64,11 +64,10 @@
self.pycode = code
eval.Frame.__init__(self, space, w_globals)
self.locals_stack_w = [None] * (code.co_nlocals + code.co_stacksize)
- self.nlocals = code.co_nlocals
self.valuestackdepth = code.co_nlocals
self.lastblock = None
make_sure_not_resized(self.locals_stack_w)
- check_nonneg(self.nlocals)
+ check_nonneg(self.valuestackdepth)
#
if space.config.objspace.honor__builtins__:
self.builtin = space.builtin.pick_builtin(w_globals)
@@ -148,8 +147,8 @@
def execute_frame(self, w_inputvalue=None, operr=None):
"""Execute this frame. Main entry point to the interpreter.
The optional arguments are there to handle a generator's frame:
- w_inputvalue is for generator.send()) and operr is for
- generator.throw()).
+ w_inputvalue is for generator.send() and operr is for
+ generator.throw().
"""
self = hint(self, stm_write=True)
hint(self.locals_stack_w, stm_write=True)
@@ -202,7 +201,7 @@
def popvalue(self):
depth = self.valuestackdepth - 1
- assert depth >= self.nlocals, "pop from empty value stack"
+ assert depth >= self.pycode.co_nlocals, "pop from empty value stack"
w_object = self.locals_stack_w[depth]
self.locals_stack_w[depth] = None
self.valuestackdepth = depth
@@ -230,7 +229,7 @@
def peekvalues(self, n):
values_w = [None] * n
base = self.valuestackdepth - n
- assert base >= self.nlocals
+ assert base >= self.pycode.co_nlocals
while True:
n -= 1
if n < 0:
@@ -242,7 +241,8 @@
def dropvalues(self, n):
n = hint(n, promote=True)
finaldepth = self.valuestackdepth - n
- assert finaldepth >= self.nlocals, "stack underflow in dropvalues()"
+ assert finaldepth >= self.pycode.co_nlocals, (
+ "stack underflow in dropvalues()")
while True:
n -= 1
if n < 0:
@@ -274,13 +274,15 @@
# Contrast this with CPython where it's PEEK(-1).
index_from_top = hint(index_from_top, promote=True)
index = self.valuestackdepth + ~index_from_top
- assert index >= self.nlocals, "peek past the bottom of the stack"
+ assert index >= self.pycode.co_nlocals, (
+ "peek past the bottom of the stack")
return self.locals_stack_w[index]
def settopvalue(self, w_object, index_from_top=0):
index_from_top = hint(index_from_top, promote=True)
index = self.valuestackdepth + ~index_from_top
- assert index >= self.nlocals, "settop past the bottom of the stack"
+ assert index >= self.pycode.co_nlocals, (
+ "settop past the bottom of the stack")
self.locals_stack_w[index] = w_object
@jit.unroll_safe
@@ -327,12 +329,13 @@
else:
f_lineno = self.f_lineno
- values_w = self.locals_stack_w[self.nlocals:self.valuestackdepth]
+ nlocals = self.pycode.co_nlocals
+ values_w = self.locals_stack_w[nlocals:self.valuestackdepth]
w_valuestack = maker.slp_into_tuple_with_nulls(space, values_w)
w_blockstack = nt([block._get_state_(space) for block in self.get_blocklist()])
w_fastlocals = maker.slp_into_tuple_with_nulls(
- space, self.locals_stack_w[:self.nlocals])
+ space, self.locals_stack_w[:nlocals])
if self.last_exception is None:
w_exc_value = space.w_None
w_tb = space.w_None
@@ -449,7 +452,7 @@
"""Initialize the fast locals from a list of values,
where the order is according to self.pycode.signature()."""
scope_len = len(scope_w)
- if scope_len > self.nlocals:
+ if scope_len > self.pycode.co_nlocals:
raise ValueError, "new fastscope is longer than the allocated area"
# don't assign directly to 'locals_stack_w[:scope_len]' to be
# virtualizable-friendly
@@ -463,7 +466,7 @@
pass
def getfastscopelength(self):
- return self.nlocals
+ return self.pycode.co_nlocals
def getclosure(self):
return None
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -2221,6 +2221,35 @@
print 'step 4 ok'
print '-'*79
+ def test_guard_not_invalidated_and_label(self):
+ # test that the guard_not_invalidated reserves enough room before
+ # the label. If it doesn't, then in this example after we invalidate
+ # the guard, jumping to the label will hit the invalidation code too
+ cpu = self.cpu
+ i0 = BoxInt()
+ faildescr = BasicFailDescr(1)
+ labeldescr = TargetToken()
+ ops = [
+ ResOperation(rop.GUARD_NOT_INVALIDATED, [], None, descr=faildescr),
+ ResOperation(rop.LABEL, [i0], None, descr=labeldescr),
+ ResOperation(rop.FINISH, [i0], None, descr=BasicFailDescr(3)),
+ ]
+ ops[0].setfailargs([])
+ looptoken = JitCellToken()
+ self.cpu.compile_loop([i0], ops, looptoken)
+ # mark as failing
+ self.cpu.invalidate_loop(looptoken)
+ # attach a bridge
+ i2 = BoxInt()
+ ops = [
+ ResOperation(rop.JUMP, [ConstInt(333)], None, descr=labeldescr),
+ ]
+ self.cpu.compile_bridge(faildescr, [], ops, looptoken)
+ # run: must not be caught in an infinite loop
+ fail = self.cpu.execute_token(looptoken, 16)
+ assert fail.identifier == 3
+ assert self.cpu.get_latest_value_int(0) == 333
+
# pure do_ / descr features
def test_do_operations(self):
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -165,7 +165,6 @@
self.jump_target_descr = None
self.close_stack_struct = 0
self.final_jump_op = None
- self.min_bytes_before_label = 0
def _prepare(self, inputargs, operations, allgcrefs):
self.fm = X86FrameManager()
@@ -199,8 +198,13 @@
operations = self._prepare(inputargs, operations, allgcrefs)
self._update_bindings(arglocs, inputargs)
self.param_depth = prev_depths[1]
+ self.min_bytes_before_label = 0
return operations
+ def ensure_next_label_is_at_least_at_position(self, at_least_position):
+ self.min_bytes_before_label = max(self.min_bytes_before_label,
+ at_least_position)
+
def reserve_param(self, n):
self.param_depth = max(self.param_depth, n)
@@ -468,7 +472,11 @@
self.assembler.mc.mark_op(None) # end of the loop
def flush_loop(self):
- # rare case: if the loop is too short, pad with NOPs
+ # rare case: if the loop is too short, or if we are just after
+ # a GUARD_NOT_INVALIDATED, pad with NOPs. Important! This must
+ # be called to ensure that there are enough bytes produced,
+ # because GUARD_NOT_INVALIDATED or redirect_call_assembler()
+ # will maybe overwrite them.
mc = self.assembler.mc
while mc.get_relative_pos() < self.min_bytes_before_label:
mc.NOP()
@@ -558,7 +566,15 @@
def consider_guard_no_exception(self, op):
self.perform_guard(op, [], None)
- consider_guard_not_invalidated = consider_guard_no_exception
+ def consider_guard_not_invalidated(self, op):
+ mc = self.assembler.mc
+ n = mc.get_relative_pos()
+ self.perform_guard(op, [], None)
+ assert n == mc.get_relative_pos()
+ # ensure that the next label is at least 5 bytes farther than
+ # the current position. Otherwise, when invalidating the guard,
+ # we would overwrite randomly the next label's position.
+ self.ensure_next_label_is_at_least_at_position(n + 5)
def consider_guard_exception(self, op):
loc = self.rm.make_sure_var_in_reg(op.getarg(0))
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
@@ -23,6 +23,7 @@
from pypy.interpreter.function import StaticMethod
from pypy.objspace.std.sliceobject import W_SliceObject
from pypy.module.__builtin__.descriptor import W_Property
+from pypy.module.__builtin__.interp_classobj import W_ClassObject
from pypy.module.__builtin__.interp_memoryview import W_MemoryView
from pypy.rlib.entrypoint import entrypoint
from pypy.rlib.unroll import unrolling_iterable
@@ -383,6 +384,7 @@
"Dict": "space.w_dict",
"Tuple": "space.w_tuple",
"List": "space.w_list",
+ "Set": "space.w_set",
"Int": "space.w_int",
"Bool": "space.w_bool",
"Float": "space.w_float",
@@ -397,6 +399,7 @@
'Module': 'space.gettypeobject(Module.typedef)',
'Property': 'space.gettypeobject(W_Property.typedef)',
'Slice': 'space.gettypeobject(W_SliceObject.typedef)',
+ 'Class': 'space.gettypeobject(W_ClassObject.typedef)',
'StaticMethod': 'space.gettypeobject(StaticMethod.typedef)',
'CFunction': 'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)',
'WrapperDescr': 'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)'
@@ -432,16 +435,16 @@
('buf', rffi.VOIDP),
('obj', PyObject),
('len', Py_ssize_t),
- # ('itemsize', Py_ssize_t),
+ ('itemsize', Py_ssize_t),
- # ('readonly', lltype.Signed),
- # ('ndim', lltype.Signed),
- # ('format', rffi.CCHARP),
- # ('shape', Py_ssize_tP),
- # ('strides', Py_ssize_tP),
- # ('suboffets', Py_ssize_tP),
- # ('smalltable', rffi.CFixedArray(Py_ssize_t, 2)),
- # ('internal', rffi.VOIDP)
+ ('readonly', lltype.Signed),
+ ('ndim', lltype.Signed),
+ ('format', rffi.CCHARP),
+ ('shape', Py_ssize_tP),
+ ('strides', Py_ssize_tP),
+ ('suboffsets', Py_ssize_tP),
+ #('smalltable', rffi.CFixedArray(Py_ssize_t, 2)),
+ ('internal', rffi.VOIDP)
))
@specialize.memo()
diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py
--- a/pypy/module/cpyext/dictobject.py
+++ b/pypy/module/cpyext/dictobject.py
@@ -6,6 +6,7 @@
from pypy.module.cpyext.pyobject import RefcountState
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.interpreter.error import OperationError
+from pypy.rlib.objectmodel import specialize
@cpython_api([], PyObject)
def PyDict_New(space):
@@ -191,3 +192,24 @@
raise
return 0
return 1
+
+ at specialize.memo()
+def make_frozendict(space):
+ return space.appexec([], '''():
+ import collections
+ class FrozenDict(collections.Mapping):
+ def __init__(self, *args, **kwargs):
+ self._d = dict(*args, **kwargs)
+ def __iter__(self):
+ return iter(self._d)
+ def __len__(self):
+ return len(self._d)
+ def __getitem__(self, key):
+ return self._d[key]
+ return FrozenDict''')
+
+ at cpython_api([PyObject], PyObject)
+def PyDictProxy_New(space, w_dict):
+ w_frozendict = make_frozendict(space)
+ return space.call_function(w_frozendict, w_dict)
+
diff --git a/pypy/module/cpyext/include/methodobject.h b/pypy/module/cpyext/include/methodobject.h
--- a/pypy/module/cpyext/include/methodobject.h
+++ b/pypy/module/cpyext/include/methodobject.h
@@ -26,6 +26,7 @@
PyObject_HEAD
PyMethodDef *m_ml; /* Description of the C function to call */
PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
+ PyObject *m_module; /* The __module__ attribute, can be anything */
} PyCFunctionObject;
/* Flag passed to newmethodobject */
diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -131,18 +131,18 @@
/* This is Py_ssize_t so it can be
pointed to by strides in simple case.*/
- /* Py_ssize_t itemsize; */
- /* int readonly; */
- /* int ndim; */
- /* char *format; */
- /* Py_ssize_t *shape; */
- /* Py_ssize_t *strides; */
- /* Py_ssize_t *suboffsets; */
+ Py_ssize_t itemsize;
+ int readonly;
+ int ndim;
+ char *format;
+ Py_ssize_t *shape;
+ Py_ssize_t *strides;
+ Py_ssize_t *suboffsets;
/* static store for shape and strides of
mono-dimensional buffers. */
/* Py_ssize_t smalltable[2]; */
- /* void *internal; */
+ void *internal;
} Py_buffer;
diff --git a/pypy/module/cpyext/include/pystate.h b/pypy/module/cpyext/include/pystate.h
--- a/pypy/module/cpyext/include/pystate.h
+++ b/pypy/module/cpyext/include/pystate.h
@@ -10,6 +10,7 @@
typedef struct _ts {
PyInterpreterState *interp;
+ PyObject *dict; /* Stores per-thread state */
} PyThreadState;
#define Py_BEGIN_ALLOW_THREADS { \
@@ -24,4 +25,6 @@
enum {PyGILState_LOCKED, PyGILState_UNLOCKED}
PyGILState_STATE;
+#define PyThreadState_GET() PyThreadState_Get()
+
#endif /* !Py_PYSTATE_H */
diff --git a/pypy/module/cpyext/include/pythread.h b/pypy/module/cpyext/include/pythread.h
--- a/pypy/module/cpyext/include/pythread.h
+++ b/pypy/module/cpyext/include/pythread.h
@@ -1,6 +1,8 @@
#ifndef Py_PYTHREAD_H
#define Py_PYTHREAD_H
+#define WITH_THREAD
+
typedef void *PyThread_type_lock;
#define WAIT_LOCK 1
#define NOWAIT_LOCK 0
diff --git a/pypy/module/cpyext/include/structmember.h b/pypy/module/cpyext/include/structmember.h
--- a/pypy/module/cpyext/include/structmember.h
+++ b/pypy/module/cpyext/include/structmember.h
@@ -20,7 +20,7 @@
} PyMemberDef;
-/* Types */
+/* Types. These constants are also in structmemberdefs.py. */
#define T_SHORT 0
#define T_INT 1
#define T_LONG 2
@@ -42,9 +42,12 @@
#define T_LONGLONG 17
#define T_ULONGLONG 18
-/* Flags */
+/* Flags. These constants are also in structmemberdefs.py. */
#define READONLY 1
#define RO READONLY /* Shorthand */
+#define READ_RESTRICTED 2
+#define PY_WRITE_RESTRICTED 4
+#define RESTRICTED (READ_RESTRICTED | PY_WRITE_RESTRICTED)
#ifdef __cplusplus
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -32,6 +32,7 @@
PyObjectFields + (
('m_ml', lltype.Ptr(PyMethodDef)),
('m_self', PyObject),
+ ('m_module', PyObject),
))
PyCFunctionObject = lltype.Ptr(PyCFunctionObjectStruct)
@@ -47,11 +48,13 @@
assert isinstance(w_obj, W_PyCFunctionObject)
py_func.c_m_ml = w_obj.ml
py_func.c_m_self = make_ref(space, w_obj.w_self)
+ py_func.c_m_module = make_ref(space, w_obj.w_module)
@cpython_api([PyObject], lltype.Void, external=False)
def cfunction_dealloc(space, py_obj):
py_func = rffi.cast(PyCFunctionObject, py_obj)
Py_DecRef(space, py_func.c_m_self)
+ Py_DecRef(space, py_func.c_m_module)
from pypy.module.cpyext.object import PyObject_dealloc
PyObject_dealloc(space, py_obj)
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
@@ -381,6 +381,15 @@
This is the equivalent of the Python expression hash(o)."""
return space.int_w(space.hash(w_obj))
+ at cpython_api([PyObject], PyObject)
+def PyObject_Dir(space, w_o):
+ """This is equivalent to the Python expression dir(o), returning a (possibly
+ empty) list of strings appropriate for the object argument, or NULL if there
+ was an error. If the argument is NULL, this is like the Python dir(),
+ returning the names of the current locals; in this case, if no execution frame
+ is active then NULL is returned but PyErr_Occurred() will return false."""
+ return space.call_function(space.builtin.get('dir'), w_o)
+
@cpython_api([PyObject, rffi.CCHARPP, Py_ssize_tP], rffi.INT_real, error=-1)
def PyObject_AsCharBuffer(space, obj, bufferp, sizep):
"""Returns a pointer to a read-only memory location usable as
@@ -430,6 +439,8 @@
return 0
+PyBUF_WRITABLE = 0x0001 # Copied from object.h
+
@cpython_api([lltype.Ptr(Py_buffer), PyObject, rffi.VOIDP, Py_ssize_t,
lltype.Signed, lltype.Signed], rffi.INT, error=CANNOT_FAIL)
def PyBuffer_FillInfo(space, view, obj, buf, length, readonly, flags):
@@ -445,6 +456,18 @@
view.c_len = length
view.c_obj = obj
Py_IncRef(space, obj)
+ view.c_itemsize = 1
+ if flags & PyBUF_WRITABLE:
+ rffi.setintfield(view, 'c_readonly', 0)
+ else:
+ rffi.setintfield(view, 'c_readonly', 1)
+ rffi.setintfield(view, 'c_ndim', 0)
+ view.c_format = lltype.nullptr(rffi.CCHARP.TO)
+ view.c_shape = lltype.nullptr(Py_ssize_tP.TO)
+ view.c_strides = lltype.nullptr(Py_ssize_tP.TO)
+ view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO)
+ view.c_internal = lltype.nullptr(rffi.VOIDP.TO)
+
return 0
diff --git a/pypy/module/cpyext/pyfile.py b/pypy/module/cpyext/pyfile.py
--- a/pypy/module/cpyext/pyfile.py
+++ b/pypy/module/cpyext/pyfile.py
@@ -1,7 +1,8 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
- cpython_api, CONST_STRING, FILEP, build_type_checkers)
+ cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, build_type_checkers)
from pypy.module.cpyext.pyobject import PyObject, borrow_from
+from pypy.module.cpyext.object import Py_PRINT_RAW
from pypy.interpreter.error import OperationError
from pypy.module._file.interp_file import W_File
@@ -61,11 +62,49 @@
def PyFile_WriteString(space, s, w_p):
"""Write string s to file object p. Return 0 on success or -1 on
failure; the appropriate exception will be set."""
- w_s = space.wrap(rffi.charp2str(s))
- space.call_method(w_p, "write", w_s)
+ w_str = space.wrap(rffi.charp2str(s))
+ space.call_method(w_p, "write", w_str)
+ return 0
+
+ at cpython_api([PyObject, PyObject, rffi.INT_real], rffi.INT_real, error=-1)
+def PyFile_WriteObject(space, w_obj, w_p, flags):
+ """
+ Write object obj to file object p. The only supported flag for flags is
+ Py_PRINT_RAW; if given, the str() of the object is written
+ instead of the repr(). Return 0 on success or -1 on failure; the
+ appropriate exception will be set."""
+ if rffi.cast(lltype.Signed, flags) & Py_PRINT_RAW:
+ w_str = space.str(w_obj)
+ else:
+ w_str = space.repr(w_obj)
+ space.call_method(w_p, "write", w_str)
return 0
@cpython_api([PyObject], PyObject)
def PyFile_Name(space, w_p):
"""Return the name of the file specified by p as a string object."""
- return borrow_from(w_p, space.getattr(w_p, space.wrap("name")))
\ No newline at end of file
+ return borrow_from(w_p, space.getattr(w_p, space.wrap("name")))
+
+ at cpython_api([PyObject, rffi.INT_real], rffi.INT_real, error=CANNOT_FAIL)
+def PyFile_SoftSpace(space, w_p, newflag):
+ """
+ This function exists for internal use by the interpreter. Set the
+ softspace attribute of p to newflag and return the previous value.
+ p does not have to be a file object for this function to work
+ properly; any object is supported (thought its only interesting if
+ the softspace attribute can be set). This function clears any
+ errors, and will return 0 as the previous value if the attribute
+ either does not exist or if there were errors in retrieving it.
+ There is no way to detect errors from this function, but doing so
+ should not be needed."""
+ try:
+ if rffi.cast(lltype.Signed, newflag):
+ w_newflag = space.w_True
+ else:
+ w_newflag = space.w_False
+ oldflag = space.int_w(space.getattr(w_p, space.wrap("softspace")))
+ space.setattr(w_p, space.wrap("softspace"), w_newflag)
+ return oldflag
+ except OperationError, e:
+ return 0
+
diff --git a/pypy/module/cpyext/pystate.py b/pypy/module/cpyext/pystate.py
--- a/pypy/module/cpyext/pystate.py
+++ b/pypy/module/cpyext/pystate.py
@@ -1,12 +1,19 @@
from pypy.module.cpyext.api import (
cpython_api, generic_cpy_call, CANNOT_FAIL, CConfig, cpython_struct)
+from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, make_ref
from pypy.rpython.lltypesystem import rffi, lltype
PyInterpreterStateStruct = lltype.ForwardReference()
PyInterpreterState = lltype.Ptr(PyInterpreterStateStruct)
cpython_struct(
- "PyInterpreterState", [('next', PyInterpreterState)], PyInterpreterStateStruct)
-PyThreadState = lltype.Ptr(cpython_struct("PyThreadState", [('interp', PyInterpreterState)]))
+ "PyInterpreterState",
+ [('next', PyInterpreterState)],
+ PyInterpreterStateStruct)
+PyThreadState = lltype.Ptr(cpython_struct(
+ "PyThreadState",
+ [('interp', PyInterpreterState),
+ ('dict', PyObject),
+ ]))
@cpython_api([], PyThreadState, error=CANNOT_FAIL)
def PyEval_SaveThread(space):
@@ -38,41 +45,49 @@
return 1
# XXX: might be generally useful
-def encapsulator(T, flavor='raw'):
+def encapsulator(T, flavor='raw', dealloc=None):
class MemoryCapsule(object):
- def __init__(self, alloc=True):
- if alloc:
+ def __init__(self, space):
+ self.space = space
+ if space is not None:
self.memory = lltype.malloc(T, flavor=flavor)
else:
self.memory = lltype.nullptr(T)
def __del__(self):
if self.memory:
+ if dealloc and self.space:
+ dealloc(self.memory, self.space)
lltype.free(self.memory, flavor=flavor)
return MemoryCapsule
-ThreadStateCapsule = encapsulator(PyThreadState.TO)
+def ThreadState_dealloc(ts, space):
+ assert space is not None
+ Py_DecRef(space, ts.c_dict)
+ThreadStateCapsule = encapsulator(PyThreadState.TO,
+ dealloc=ThreadState_dealloc)
from pypy.interpreter.executioncontext import ExecutionContext
-ExecutionContext.cpyext_threadstate = ThreadStateCapsule(alloc=False)
+ExecutionContext.cpyext_threadstate = ThreadStateCapsule(None)
class InterpreterState(object):
def __init__(self, space):
self.interpreter_state = lltype.malloc(
PyInterpreterState.TO, flavor='raw', zero=True, immortal=True)
- def new_thread_state(self):
- capsule = ThreadStateCapsule()
+ def new_thread_state(self, space):
+ capsule = ThreadStateCapsule(space)
ts = capsule.memory
ts.c_interp = self.interpreter_state
+ ts.c_dict = make_ref(space, space.newdict())
return capsule
def get_thread_state(self, space):
ec = space.getexecutioncontext()
- return self._get_thread_state(ec).memory
+ return self._get_thread_state(space, ec).memory
- def _get_thread_state(self, ec):
+ def _get_thread_state(self, space, ec):
if ec.cpyext_threadstate.memory == lltype.nullptr(PyThreadState.TO):
- ec.cpyext_threadstate = self.new_thread_state()
+ ec.cpyext_threadstate = self.new_thread_state(space)
return ec.cpyext_threadstate
@@ -81,6 +96,11 @@
state = space.fromcache(InterpreterState)
return state.get_thread_state(space)
+ at cpython_api([], PyObject, error=CANNOT_FAIL)
+def PyThreadState_GetDict(space):
+ state = space.fromcache(InterpreterState)
+ return state.get_thread_state(space).c_dict
+
@cpython_api([PyThreadState], PyThreadState, error=CANNOT_FAIL)
def PyThreadState_Swap(space, tstate):
"""Swap the current thread state with the thread state given by the argument
diff --git a/pypy/module/cpyext/pythonrun.py b/pypy/module/cpyext/pythonrun.py
--- a/pypy/module/cpyext/pythonrun.py
+++ b/pypy/module/cpyext/pythonrun.py
@@ -14,6 +14,20 @@
value."""
return space.fromcache(State).get_programname()
+ at cpython_api([], rffi.CCHARP)
+def Py_GetVersion(space):
+ """Return the version of this Python interpreter. This is a
+ string that looks something like
+
+ "1.5 (\#67, Dec 31 1997, 22:34:28) [GCC 2.7.2.2]"
+
+ The first word (up to the first space character) is the current
+ Python version; the first three characters are the major and minor
+ version separated by a period. The returned string points into
+ static storage; the caller should not modify its value. The value
+ is available to Python code as sys.version."""
+ return space.fromcache(State).get_version()
+
@cpython_api([lltype.Ptr(lltype.FuncType([], lltype.Void))], rffi.INT_real, error=-1)
def Py_AtExit(space, func_ptr):
"""Register a cleanup function to be called by Py_Finalize(). The cleanup
diff --git a/pypy/module/cpyext/setobject.py b/pypy/module/cpyext/setobject.py
--- a/pypy/module/cpyext/setobject.py
+++ b/pypy/module/cpyext/setobject.py
@@ -54,6 +54,20 @@
return 0
+ at cpython_api([PyObject], PyObject)
+def PySet_Pop(space, w_set):
+ """Return a new reference to an arbitrary object in the set, and removes the
+ object from the set. Return NULL on failure. Raise KeyError if the
+ set is empty. Raise a SystemError if set is an not an instance of
+ set or its subtype."""
+ return space.call_method(w_set, "pop")
+
+ at cpython_api([PyObject], rffi.INT_real, error=-1)
+def PySet_Clear(space, w_set):
+ """Empty an existing set of all elements."""
+ space.call_method(w_set, 'clear')
+ return 0
+
@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
def PySet_GET_SIZE(space, w_s):
"""Macro form of PySet_Size() without error checking."""
diff --git a/pypy/module/cpyext/state.py b/pypy/module/cpyext/state.py
--- a/pypy/module/cpyext/state.py
+++ b/pypy/module/cpyext/state.py
@@ -10,6 +10,7 @@
self.space = space
self.reset()
self.programname = lltype.nullptr(rffi.CCHARP.TO)
+ self.version = lltype.nullptr(rffi.CCHARP.TO)
def reset(self):
from pypy.module.cpyext.modsupport import PyMethodDef
@@ -102,6 +103,15 @@
lltype.render_immortal(self.programname)
return self.programname
+ def get_version(self):
+ if not self.version:
+ space = self.space
+ w_version = space.sys.get('version')
+ version = space.str_w(w_version)
+ self.version = rffi.str2charp(version)
+ lltype.render_immortal(self.version)
+ return self.version
+
def find_extension(self, name, path):
from pypy.module.cpyext.modsupport import PyImport_AddModule
from pypy.interpreter.module import Module
diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -250,6 +250,26 @@
s = rffi.charp2str(string)
return space.new_interned_str(s)
+ at cpython_api([PyObjectP], lltype.Void)
+def PyString_InternInPlace(space, string):
+ """Intern the argument *string in place. The argument must be the
+ address of a pointer variable pointing to a Python string object.
+ If there is an existing interned string that is the same as
+ *string, it sets *string to it (decrementing the reference count
+ of the old string object and incrementing the reference count of
+ the interned string object), otherwise it leaves *string alone and
+ interns it (incrementing its reference count). (Clarification:
+ even though there is a lot of talk about reference counts, think
+ of this function as reference-count-neutral; you own the object
+ after the call if and only if you owned it before the call.)
+
+ This function is not available in 3.x and does not have a PyBytes
+ alias."""
+ w_str = from_ref(space, string[0])
+ w_str = space.new_interned_w_str(w_str)
+ Py_DecRef(space, string[0])
+ string[0] = make_ref(space, w_str)
+
@cpython_api([PyObject, rffi.CCHARP, rffi.CCHARP], PyObject)
def PyString_AsEncodedObject(space, w_str, encoding, errors):
"""Encode a string object using the codec registered for encoding and return
diff --git a/pypy/module/cpyext/structmemberdefs.py b/pypy/module/cpyext/structmemberdefs.py
--- a/pypy/module/cpyext/structmemberdefs.py
+++ b/pypy/module/cpyext/structmemberdefs.py
@@ -1,3 +1,5 @@
+# These constants are also in include/structmember.h
+
T_SHORT = 0
T_INT = 1
T_LONG = 2
@@ -18,3 +20,6 @@
T_ULONGLONG = 18
READONLY = RO = 1
+READ_RESTRICTED = 2
+WRITE_RESTRICTED = 4
+RESTRICTED = READ_RESTRICTED | WRITE_RESTRICTED
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -1,5 +1,5 @@
from pypy.module.cpyext.api import (
- cpython_api, PyObject, PyObjectP, CANNOT_FAIL, Py_buffer
+ cpython_api, PyObject, PyObjectP, CANNOT_FAIL
)
from pypy.module.cpyext.complexobject import Py_complex_ptr as Py_complex
from pypy.rpython.lltypesystem import rffi, lltype
@@ -10,6 +10,7 @@
PyMethodDef = rffi.VOIDP
PyGetSetDef = rffi.VOIDP
PyMemberDef = rffi.VOIDP
+Py_buffer = rffi.VOIDP
va_list = rffi.VOIDP
PyDateTime_Date = rffi.VOIDP
PyDateTime_DateTime = rffi.VOIDP
@@ -32,10 +33,6 @@
def _PyObject_Del(space, op):
raise NotImplementedError
- at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
-def PyObject_CheckBuffer(space, obj):
- raise NotImplementedError
-
@cpython_api([rffi.CCHARP], Py_ssize_t, error=CANNOT_FAIL)
def PyBuffer_SizeFromFormat(space, format):
"""Return the implied ~Py_buffer.itemsize from the struct-stype
@@ -684,28 +681,6 @@
"""
raise NotImplementedError
- at cpython_api([PyObject, rffi.INT_real], rffi.INT_real, error=CANNOT_FAIL)
-def PyFile_SoftSpace(space, p, newflag):
- """
- This function exists for internal use by the interpreter. Set the
- softspace attribute of p to newflag and return the previous value.
- p does not have to be a file object for this function to work properly; any
- object is supported (thought its only interesting if the softspace
- attribute can be set). This function clears any errors, and will return 0
- as the previous value if the attribute either does not exist or if there were
- errors in retrieving it. There is no way to detect errors from this function,
- but doing so should not be needed."""
- raise NotImplementedError
-
- at cpython_api([PyObject, PyObject, rffi.INT_real], rffi.INT_real, error=-1)
-def PyFile_WriteObject(space, obj, p, flags):
- """
- Write object obj to file object p. The only supported flag for flags is
- Py_PRINT_RAW; if given, the str() of the object is written
- instead of the repr(). Return 0 on success or -1 on failure; the
- appropriate exception will be set."""
- raise NotImplementedError
-
@cpython_api([], PyObject)
def PyFloat_GetInfo(space):
"""Return a structseq instance which contains information about the
@@ -1097,19 +1072,6 @@
raise NotImplementedError
@cpython_api([], rffi.CCHARP)
-def Py_GetVersion(space):
- """Return the version of this Python interpreter. This is a string that looks
- something like
-
- "1.5 (\#67, Dec 31 1997, 22:34:28) [GCC 2.7.2.2]"
-
- The first word (up to the first space character) is the current Python version;
- the first three characters are the major and minor version separated by a
- period. The returned string points into static storage; the caller should not
- modify its value. The value is available to Python code as sys.version."""
- raise NotImplementedError
-
- at cpython_api([], rffi.CCHARP)
def Py_GetPlatform(space):
"""Return the platform identifier for the current platform. On Unix, this
is formed from the"official" name of the operating system, converted to lower
@@ -1685,15 +1647,6 @@
"""
raise NotImplementedError
- at cpython_api([PyObject], PyObject)
-def PyObject_Dir(space, o):
- """This is equivalent to the Python expression dir(o), returning a (possibly
- empty) list of strings appropriate for the object argument, or NULL if there
- was an error. If the argument is NULL, this is like the Python dir(),
- returning the names of the current locals; in this case, if no execution frame
- is active then NULL is returned but PyErr_Occurred() will return false."""
- raise NotImplementedError
-
@cpython_api([], PyFrameObject)
def PyEval_GetFrame(space):
"""Return the current thread state's frame, which is NULL if no frame is
@@ -1802,34 +1755,6 @@
building-up new frozensets with PySet_Add()."""
raise NotImplementedError
- at cpython_api([PyObject], PyObject)
-def PySet_Pop(space, set):
- """Return a new reference to an arbitrary object in the set, and removes the
- object from the set. Return NULL on failure. Raise KeyError if the
- set is empty. Raise a SystemError if set is an not an instance of
- set or its subtype."""
- raise NotImplementedError
-
- at cpython_api([PyObject], rffi.INT_real, error=-1)
-def PySet_Clear(space, set):
- """Empty an existing set of all elements."""
- raise NotImplementedError
-
- at cpython_api([PyObjectP], lltype.Void)
-def PyString_InternInPlace(space, string):
- """Intern the argument *string in place. The argument must be the address of a
- pointer variable pointing to a Python string object. If there is an existing
- interned string that is the same as *string, it sets *string to it
- (decrementing the reference count of the old string object and incrementing the
- reference count of the interned string object), otherwise it leaves *string
- alone and interns it (incrementing its reference count). (Clarification: even
- though there is a lot of talk about reference counts, think of this function as
- reference-count-neutral; you own the object after the call if and only if you
- owned it before the call.)
-
- This function is not available in 3.x and does not have a PyBytes alias."""
- raise NotImplementedError
-
@cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP, rffi.CCHARP], PyObject)
def PyString_Decode(space, s, size, encoding, errors):
"""Create an object by decoding size bytes of the encoded buffer s using the
diff --git a/pypy/module/cpyext/test/test_classobject.py b/pypy/module/cpyext/test/test_classobject.py
--- a/pypy/module/cpyext/test/test_classobject.py
+++ b/pypy/module/cpyext/test/test_classobject.py
@@ -1,4 +1,5 @@
from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from pypy.interpreter.function import Function, Method
class TestClassObject(BaseApiTest):
@@ -51,3 +52,14 @@
assert api.PyInstance_Check(w_instance)
assert space.is_true(space.call_method(space.builtin, "isinstance",
w_instance, w_class))
+
+class AppTestStringObject(AppTestCpythonExtensionBase):
+ def test_class_type(self):
+ module = self.import_extension('foo', [
+ ("get_classtype", "METH_NOARGS",
+ """
+ Py_INCREF(&PyClass_Type);
+ return &PyClass_Type;
+ """)])
+ class C: pass
+ assert module.get_classtype() is type(C)
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -744,6 +744,22 @@
print p
assert 'py' in p
+ def test_get_version(self):
+ mod = self.import_extension('foo', [
+ ('get_version', 'METH_NOARGS',
+ '''
+ char* name1 = Py_GetVersion();
+ char* name2 = Py_GetVersion();
+ if (name1 != name2)
+ Py_RETURN_FALSE;
+ return PyString_FromString(name1);
+ '''
+ ),
+ ])
+ p = mod.get_version()
+ print p
+ assert 'PyPy' in p
+
def test_no_double_imports(self):
import sys, os
try:
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
@@ -2,6 +2,7 @@
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.api import Py_ssize_tP, PyObjectP
from pypy.module.cpyext.pyobject import make_ref, from_ref
+from pypy.interpreter.error import OperationError
class TestDictObject(BaseApiTest):
def test_dict(self, space, api):
@@ -110,3 +111,13 @@
assert space.eq_w(space.len(w_copy), space.len(w_dict))
assert space.eq_w(w_copy, w_dict)
+
+ def test_dictproxy(self, space, api):
+ w_dict = space.sys.get('modules')
+ w_proxy = api.PyDictProxy_New(w_dict)
+ assert space.is_true(space.contains(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')
diff --git a/pypy/module/cpyext/test/test_methodobject.py b/pypy/module/cpyext/test/test_methodobject.py
--- a/pypy/module/cpyext/test/test_methodobject.py
+++ b/pypy/module/cpyext/test/test_methodobject.py
@@ -9,7 +9,7 @@
class AppTestMethodObject(AppTestCpythonExtensionBase):
def test_call_METH(self):
- mod = self.import_extension('foo', [
+ mod = self.import_extension('MyModule', [
('getarg_O', 'METH_O',
'''
Py_INCREF(args);
@@ -51,11 +51,23 @@
}
'''
),
+ ('getModule', 'METH_O',
+ '''
+ if(PyCFunction_Check(args)) {
+ PyCFunctionObject* func = (PyCFunctionObject*)args;
+ Py_INCREF(func->m_module);
+ return func->m_module;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
+ '''
+ ),
('isSameFunction', 'METH_O',
'''
PyCFunction ptr = PyCFunction_GetFunction(args);
if (!ptr) return NULL;
- if (ptr == foo_getarg_O)
+ if (ptr == MyModule_getarg_O)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
@@ -76,6 +88,7 @@
assert mod.getarg_OLD(1, 2) == (1, 2)
assert mod.isCFunction(mod.getarg_O) == "getarg_O"
+ assert mod.getModule(mod.getarg_O) == 'MyModule'
assert mod.isSameFunction(mod.getarg_O)
raises(TypeError, mod.isSameFunction, 1)
diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -191,6 +191,11 @@
assert api.PyObject_Unicode(space.wrap("\xe9")) is None
api.PyErr_Clear()
+ def test_dir(self, space, api):
+ w_dir = api.PyObject_Dir(space.sys)
+ assert space.isinstance_w(w_dir, space.w_list)
+ assert space.is_true(space.contains(w_dir, space.wrap('modules')))
+
class AppTestObject(AppTestCpythonExtensionBase):
def setup_class(cls):
AppTestCpythonExtensionBase.setup_class.im_func(cls)
diff --git a/pypy/module/cpyext/test/test_pyfile.py b/pypy/module/cpyext/test/test_pyfile.py
--- a/pypy/module/cpyext/test/test_pyfile.py
+++ b/pypy/module/cpyext/test/test_pyfile.py
@@ -1,5 +1,6 @@
from pypy.module.cpyext.api import fopen, fclose, fwrite
from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.object import Py_PRINT_RAW
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.tool.udir import udir
import pytest
@@ -77,3 +78,28 @@
out = out.replace('\r\n', '\n')
assert out == "test\n"
+ def test_file_writeobject(self, space, api, capfd):
+ w_obj = space.wrap("test\n")
+ w_stdout = space.sys.get("stdout")
+ api.PyFile_WriteObject(w_obj, w_stdout, Py_PRINT_RAW)
+ api.PyFile_WriteObject(w_obj, w_stdout, 0)
+ space.call_method(w_stdout, "flush")
+ out, err = capfd.readouterr()
+ out = out.replace('\r\n', '\n')
+ assert out == "test\n'test\\n'"
+
+ def test_file_softspace(self, space, api, capfd):
+ w_stdout = space.sys.get("stdout")
+ assert api.PyFile_SoftSpace(w_stdout, 1) == 0
+ assert api.PyFile_SoftSpace(w_stdout, 0) == 1
+
+ api.PyFile_SoftSpace(w_stdout, 1)
+ w_ns = space.newdict()
+ space.exec_("print 1,", w_ns, w_ns)
+ space.exec_("print 2,", w_ns, w_ns)
+ api.PyFile_SoftSpace(w_stdout, 0)
+ space.exec_("print 3", w_ns, w_ns)
+ space.call_method(w_stdout, "flush")
+ out, err = capfd.readouterr()
+ out = out.replace('\r\n', '\n')
+ assert out == " 1 23\n"
diff --git a/pypy/module/cpyext/test/test_pystate.py b/pypy/module/cpyext/test/test_pystate.py
--- a/pypy/module/cpyext/test/test_pystate.py
+++ b/pypy/module/cpyext/test/test_pystate.py
@@ -2,6 +2,7 @@
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.rpython.lltypesystem.lltype import nullptr
from pypy.module.cpyext.pystate import PyInterpreterState, PyThreadState
+from pypy.module.cpyext.pyobject import from_ref
class AppTestThreads(AppTestCpythonExtensionBase):
def test_allow_threads(self):
@@ -49,3 +50,10 @@
api.PyEval_AcquireThread(tstate)
api.PyEval_ReleaseThread(tstate)
+
+ def test_threadstate_dict(self, space, api):
+ ts = api.PyThreadState_Get()
+ ref = ts.c_dict
+ assert ref == api.PyThreadState_GetDict()
+ w_obj = from_ref(space, ref)
+ assert space.isinstance_w(w_obj, space.w_dict)
diff --git a/pypy/module/cpyext/test/test_setobject.py b/pypy/module/cpyext/test/test_setobject.py
--- a/pypy/module/cpyext/test/test_setobject.py
+++ b/pypy/module/cpyext/test/test_setobject.py
@@ -32,3 +32,13 @@
w_set = api.PySet_New(space.wrap([1,2,3,4]))
assert api.PySet_Contains(w_set, space.wrap(1))
assert not api.PySet_Contains(w_set, space.wrap(0))
+
+ def test_set_pop_clear(self, space, api):
+ w_set = api.PySet_New(space.wrap([1,2,3,4]))
+ w_obj = api.PySet_Pop(w_set)
+ assert space.int_w(w_obj) in (1,2,3,4)
+ assert space.len_w(w_set) == 3
+ api.PySet_Clear(w_set)
+ assert space.len_w(w_set) == 0
+
+
diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ b/pypy/module/cpyext/test/test_stringobject.py
@@ -166,6 +166,20 @@
res = module.test_string_format(1, "xyz")
assert res == "bla 1 ble xyz\n"
+ def test_intern_inplace(self):
+ module = self.import_extension('foo', [
+ ("test_intern_inplace", "METH_O",
+ '''
+ PyObject *s = args;
+ Py_INCREF(s);
+ PyString_InternInPlace(&s);
+ return s;
+ '''
+ )
+ ])
+ # This does not test much, but at least the refcounts are checked.
+ assert module.test_intern_inplace('s') == 's'
+
class TestString(BaseApiTest):
def test_string_resize(self, space, api):
py_str = new_empty_str(space, 10)
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
@@ -420,3 +420,12 @@
w_seq = space.wrap([u'a', u'b'])
w_joined = api.PyUnicode_Join(w_sep, w_seq)
assert space.unwrap(w_joined) == u'a<sep>b'
+
+ def test_fromordinal(self, space, api):
+ w_char = api.PyUnicode_FromOrdinal(65)
+ assert space.unwrap(w_char) == u'A'
+ w_char = api.PyUnicode_FromOrdinal(0)
+ assert space.unwrap(w_char) == u'\0'
+ w_char = api.PyUnicode_FromOrdinal(0xFFFF)
+ assert space.unwrap(w_char) == u'\uFFFF'
+
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -395,6 +395,16 @@
w_str = space.wrap(rffi.charpsize2str(s, size))
return space.call_method(w_str, 'decode', space.wrap("utf-8"))
+ at cpython_api([rffi.INT_real], PyObject)
+def PyUnicode_FromOrdinal(space, ordinal):
+ """Create a Unicode Object from the given Unicode code point ordinal.
+
+ The ordinal must be in range(0x10000) on narrow Python builds
+ (UCS2), and range(0x110000) on wide builds (UCS4). A ValueError is
+ raised in case it is not."""
+ w_ordinal = space.wrap(rffi.cast(lltype.Signed, ordinal))
+ return space.call_function(space.builtin.get('unichr'), w_ordinal)
+
@cpython_api([PyObjectP, Py_ssize_t], rffi.INT_real, error=-1)
def PyUnicode_Resize(space, ref, newsize):
# XXX always create a new string so far
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -1297,6 +1297,7 @@
nbytes = GetSetProperty(BaseArray.descr_get_nbytes),
T = GetSetProperty(BaseArray.descr_get_transpose),
+ transpose = interp2app(BaseArray.descr_get_transpose),
flat = GetSetProperty(BaseArray.descr_get_flatiter),
ravel = interp2app(BaseArray.descr_ravel),
item = interp2app(BaseArray.descr_item),
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1487,6 +1487,7 @@
a = array((range(10), range(20, 30)))
b = a.T
assert(b[:, 0] == a[0, :]).all()
+ assert (a.transpose() == b).all()
def test_flatiter(self):
from _numpypy import array, flatiter, arange
diff --git a/pypy/module/oracle/interp_error.py b/pypy/module/oracle/interp_error.py
--- a/pypy/module/oracle/interp_error.py
+++ b/pypy/module/oracle/interp_error.py
@@ -72,7 +72,7 @@
get(space).w_InternalError,
space.wrap("No Oracle error?"))
- self.code = codeptr[0]
+ self.code = rffi.cast(lltype.Signed, codeptr[0])
self.w_message = config.w_string(space, textbuf)
finally:
lltype.free(codeptr, flavor='raw')
diff --git a/pypy/module/oracle/interp_variable.py b/pypy/module/oracle/interp_variable.py
--- a/pypy/module/oracle/interp_variable.py
+++ b/pypy/module/oracle/interp_variable.py
@@ -359,14 +359,14 @@
# Verifies that truncation or other problems did not take place on
# retrieve.
if self.isVariableLength:
- if rffi.cast(lltype.Signed, self.returnCode[pos]) != 0:
+ error_code = rffi.cast(lltype.Signed, self.returnCode[pos])
+ if error_code != 0:
error = W_Error(space, self.environment,
"Variable_VerifyFetch()", 0)
- error.code = self.returnCode[pos]
+ error.code = error_code
error.message = space.wrap(
"column at array pos %d fetched with error: %d" %
- (pos,
- rffi.cast(lltype.Signed, self.returnCode[pos])))
+ (pos, error_code))
w_error = get(space).w_DatabaseError
raise OperationError(get(space).w_DatabaseError,
diff --git a/pypy/module/test_lib_pypy/test_datetime.py b/pypy/module/test_lib_pypy/test_datetime.py
--- a/pypy/module/test_lib_pypy/test_datetime.py
+++ b/pypy/module/test_lib_pypy/test_datetime.py
@@ -1,7 +1,10 @@
"""Additional tests for datetime."""
+import py
+
import time
import datetime
+import copy
import os
def test_utcfromtimestamp():
@@ -26,3 +29,18 @@
def test_utcfromtimestamp_microsecond():
dt = datetime.datetime.utcfromtimestamp(0)
assert isinstance(dt.microsecond, int)
+
+
+def test_integer_args():
+ with py.test.raises(TypeError):
+ datetime.datetime(10, 10, 10.)
+ with py.test.raises(TypeError):
+ datetime.datetime(10, 10, 10, 10, 10.)
+ with py.test.raises(TypeError):
+ datetime.datetime(10, 10, 10, 10, 10, 10.)
+
+def test_utcnow_microsecond():
+ dt = datetime.datetime.utcnow()
+ assert type(dt.microsecond) is int
+
+ copy.copy(dt)
\ No newline at end of file
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -326,4 +326,5 @@
return w_some_obj()
FakeObjSpace.sys = FakeModule()
FakeObjSpace.sys.filesystemencoding = 'foobar'
+FakeObjSpace.sys.defaultencoding = 'ascii'
FakeObjSpace.builtin = FakeModule()
diff --git a/pypy/objspace/flow/flowcontext.py b/pypy/objspace/flow/flowcontext.py
--- a/pypy/objspace/flow/flowcontext.py
+++ b/pypy/objspace/flow/flowcontext.py
@@ -410,7 +410,7 @@
w_new = Constant(newvalue)
f = self.crnt_frame
stack_items_w = f.locals_stack_w
- for i in range(f.valuestackdepth-1, f.nlocals-1, -1):
+ for i in range(f.valuestackdepth-1, f.pycode.co_nlocals-1, -1):
w_v = stack_items_w[i]
if isinstance(w_v, Constant):
if w_v.value is oldvalue:
diff --git a/pypy/objspace/flow/test/test_framestate.py b/pypy/objspace/flow/test/test_framestate.py
--- a/pypy/objspace/flow/test/test_framestate.py
+++ b/pypy/objspace/flow/test/test_framestate.py
@@ -25,7 +25,7 @@
dummy = Constant(None)
#dummy.dummy = True
arg_list = ([Variable() for i in range(formalargcount)] +
- [dummy] * (frame.nlocals - formalargcount))
+ [dummy] * (frame.pycode.co_nlocals - formalargcount))
frame.setfastscope(arg_list)
return frame
@@ -42,7 +42,7 @@
def test_neq_hacked_framestate(self):
frame = self.getframe(self.func_simple)
fs1 = FrameState(frame)
- frame.locals_stack_w[frame.nlocals-1] = Variable()
+ frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
fs2 = FrameState(frame)
assert fs1 != fs2
@@ -55,7 +55,7 @@
def test_union_on_hacked_framestates(self):
frame = self.getframe(self.func_simple)
fs1 = FrameState(frame)
- frame.locals_stack_w[frame.nlocals-1] = Variable()
+ frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
fs2 = FrameState(frame)
assert fs1.union(fs2) == fs2 # fs2 is more general
assert fs2.union(fs1) == fs2 # fs2 is more general
@@ -63,7 +63,7 @@
def test_restore_frame(self):
frame = self.getframe(self.func_simple)
fs1 = FrameState(frame)
- frame.locals_stack_w[frame.nlocals-1] = Variable()
+ frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
fs1.restoreframe(frame)
assert fs1 == FrameState(frame)
@@ -82,7 +82,7 @@
def test_getoutputargs(self):
frame = self.getframe(self.func_simple)
fs1 = FrameState(frame)
- frame.locals_stack_w[frame.nlocals-1] = Variable()
+ frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
fs2 = FrameState(frame)
outputargs = fs1.getoutputargs(fs2)
# 'x' -> 'x' is a Variable
@@ -92,16 +92,16 @@
def test_union_different_constants(self):
frame = self.getframe(self.func_simple)
fs1 = FrameState(frame)
- frame.locals_stack_w[frame.nlocals-1] = Constant(42)
+ frame.locals_stack_w[frame.pycode.co_nlocals-1] = Constant(42)
fs2 = FrameState(frame)
fs3 = fs1.union(fs2)
fs3.restoreframe(frame)
- assert isinstance(frame.locals_stack_w[frame.nlocals-1], Variable)
- # ^^^ generalized
+ assert isinstance(frame.locals_stack_w[frame.pycode.co_nlocals-1],
+ Variable) # generalized
def test_union_spectag(self):
frame = self.getframe(self.func_simple)
fs1 = FrameState(frame)
- frame.locals_stack_w[frame.nlocals-1] = Constant(SpecTag())
+ frame.locals_stack_w[frame.pycode.co_nlocals-1] = Constant(SpecTag())
fs2 = FrameState(frame)
assert fs1.union(fs2) is None # UnionError
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -238,7 +238,7 @@
self = jit.promote(self)
if argchain.numargs != len(self.argtypes):
raise TypeError, 'Wrong number of arguments: %d expected, got %d' %\
- (argchain.numargs, len(self.argtypes))
+ (len(self.argtypes), argchain.numargs)
ll_args = self._prepare()
i = 0
arg = argchain.first
diff --git a/pypy/translator/c/database.py b/pypy/translator/c/database.py
--- a/pypy/translator/c/database.py
+++ b/pypy/translator/c/database.py
@@ -28,11 +28,13 @@
gctransformer = None
def __init__(self, translator=None, standalone=False,
+ cpython_extension=False,
gcpolicyclass=None,
thread_enabled=False,
sandbox=False):
self.translator = translator
self.standalone = standalone
+ self.cpython_extension = cpython_extension
self.sandbox = sandbox
if gcpolicyclass is None:
gcpolicyclass = gc.RefcountingGcPolicy
diff --git a/pypy/translator/c/dlltool.py b/pypy/translator/c/dlltool.py
--- a/pypy/translator/c/dlltool.py
+++ b/pypy/translator/c/dlltool.py
@@ -14,11 +14,14 @@
CBuilder.__init__(self, *args, **kwds)
def getentrypointptr(self):
+ entrypoints = []
bk = self.translator.annotator.bookkeeper
- graphs = [bk.getdesc(f).cachedgraph(None) for f, _ in self.functions]
- return [getfunctionptr(graph) for graph in graphs]
+ for f, _ in self.functions:
+ graph = bk.getdesc(f).getuniquegraph()
+ entrypoints.append(getfunctionptr(graph))
+ return entrypoints
- def gen_makefile(self, targetdir):
+ def gen_makefile(self, targetdir, exe_name=None):
pass # XXX finish
def compile(self):
diff --git a/pypy/translator/c/extfunc.py b/pypy/translator/c/extfunc.py
--- a/pypy/translator/c/extfunc.py
+++ b/pypy/translator/c/extfunc.py
@@ -78,7 +78,7 @@
yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.fn_exception_match)
yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.fn_type_of_exc_inst)
yield ('RPYTHON_RAISE_OSERROR', exceptiondata.fn_raise_OSError)
- if not db.standalone:
+ if db.cpython_extension:
yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.fn_pyexcclass2exc)
yield ('RPyExceptionOccurred1', exctransformer.rpyexc_occured_ptr.value)
diff --git a/pypy/translator/c/gcc/trackgcroot.py b/pypy/translator/c/gcc/trackgcroot.py
--- a/pypy/translator/c/gcc/trackgcroot.py
+++ b/pypy/translator/c/gcc/trackgcroot.py
@@ -471,8 +471,8 @@
return []
IGNORE_OPS_WITH_PREFIXES = dict.fromkeys([
- 'cmp', 'test', 'set', 'sahf', 'lahf', 'cltd', 'cld', 'std',
- 'rep', 'movs', 'lods', 'stos', 'scas', 'cwtl', 'cwde', 'prefetch',
+ 'cmp', 'test', 'set', 'sahf', 'lahf', 'cld', 'std',
+ 'rep', 'movs', 'lods', 'stos', 'scas', 'cwde', 'prefetch',
# floating-point operations cannot produce GC pointers
'f',
'cvt', 'ucomi', 'comi', 'subs', 'subp' , 'adds', 'addp', 'xorp',
@@ -485,6 +485,8 @@
'bswap', 'bt', 'rdtsc',
'punpck', 'pshufd', 'pcmp', 'pand', 'psllw', 'pslld', 'psllq',
'paddq', 'pinsr',
+ # sign-extending moves should not produce GC pointers
+ 'cbtw', 'cwtl', 'cwtd', 'cltd', 'cltq', 'cqto',
# zero-extending moves should not produce GC pointers
'movz',
# locked operations should not move GC pointers, at least so far
diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py
--- a/pypy/translator/c/genc.py
+++ b/pypy/translator/c/genc.py
@@ -111,6 +111,7 @@
_compiled = False
modulename = None
split = False
+ cpython_extension = False
def __init__(self, translator, entrypoint, config, gcpolicy=None,
secondary_entrypoints=()):
@@ -144,6 +145,7 @@
raise NotImplementedError("--gcrootfinder=asmgcc requires standalone")
db = LowLevelDatabase(translator, standalone=self.standalone,
+ cpython_extension=self.cpython_extension,
gcpolicyclass=gcpolicyclass,
thread_enabled=self.config.translation.thread,
sandbox=self.config.translation.sandbox)
@@ -249,6 +251,8 @@
CBuilder.have___thread = self.translator.platform.check___thread()
if not self.standalone:
assert not self.config.translation.instrument
+ if self.cpython_extension:
+ defines['PYPY_CPYTHON_EXTENSION'] = 1
else:
defines['PYPY_STANDALONE'] = db.get(pf)
if self.config.translation.instrument:
@@ -320,13 +324,18 @@
class CExtModuleBuilder(CBuilder):
standalone = False
+ cpython_extension = True
_module = None
_wrapper = None
def get_eci(self):
from distutils import sysconfig
python_inc = sysconfig.get_python_inc()
- eci = ExternalCompilationInfo(include_dirs=[python_inc])
+ eci = ExternalCompilationInfo(
+ include_dirs=[python_inc],
+ includes=["Python.h",
+ ],
+ )
return eci.merge(CBuilder.get_eci(self))
def getentrypointptr(self): # xxx
diff --git a/pypy/translator/c/src/exception.h b/pypy/translator/c/src/exception.h
--- a/pypy/translator/c/src/exception.h
+++ b/pypy/translator/c/src/exception.h
@@ -2,7 +2,7 @@
/************************************************************/
/*** C header subsection: exceptions ***/
-#if !defined(PYPY_STANDALONE) && !defined(PYPY_NOT_MAIN_FILE)
+#if defined(PYPY_CPYTHON_EXTENSION) && !defined(PYPY_NOT_MAIN_FILE)
PyObject *RPythonError;
#endif
@@ -74,7 +74,7 @@
RPyRaiseException(RPYTHON_TYPE_OF_EXC_INST(rexc), rexc);
}
-#ifndef PYPY_STANDALONE
+#ifdef PYPY_CPYTHON_EXTENSION
void RPyConvertExceptionFromCPython(void)
{
/* convert the CPython exception to an RPython one */
diff --git a/pypy/translator/c/src/g_include.h b/pypy/translator/c/src/g_include.h
--- a/pypy/translator/c/src/g_include.h
+++ b/pypy/translator/c/src/g_include.h
@@ -2,7 +2,7 @@
/************************************************************/
/*** C header file for code produced by genc.py ***/
-#ifndef PYPY_STANDALONE
+#ifdef PYPY_CPYTHON_EXTENSION
# include "Python.h"
# include "compile.h"
# include "frameobject.h"
diff --git a/pypy/translator/c/src/g_prerequisite.h b/pypy/translator/c/src/g_prerequisite.h
--- a/pypy/translator/c/src/g_prerequisite.h
+++ b/pypy/translator/c/src/g_prerequisite.h
@@ -5,8 +5,6 @@
#ifdef PYPY_STANDALONE
# include "src/commondefs.h"
-#else
-# include "Python.h"
#endif
#ifdef _WIN32
diff --git a/pypy/translator/c/src/pyobj.h b/pypy/translator/c/src/pyobj.h
--- a/pypy/translator/c/src/pyobj.h
+++ b/pypy/translator/c/src/pyobj.h
@@ -2,7 +2,7 @@
/************************************************************/
/*** C header subsection: untyped operations ***/
/*** as OP_XXX() macros calling the CPython API ***/
-
+#ifdef PYPY_CPYTHON_EXTENSION
#define op_bool(r,what) { \
int _retval = what; \
@@ -261,3 +261,5 @@
}
#endif
+
+#endif /* PYPY_CPYTHON_EXTENSION */
diff --git a/pypy/translator/c/src/support.h b/pypy/translator/c/src/support.h
--- a/pypy/translator/c/src/support.h
+++ b/pypy/translator/c/src/support.h
@@ -104,7 +104,7 @@
# define RPyBareItem(array, index) ((array)[index])
#endif
-#ifndef PYPY_STANDALONE
+#ifdef PYPY_CPYTHON_EXTENSION
/* prototypes */
diff --git a/pypy/translator/c/test/test_dlltool.py b/pypy/translator/c/test/test_dlltool.py
--- a/pypy/translator/c/test/test_dlltool.py
+++ b/pypy/translator/c/test/test_dlltool.py
@@ -2,7 +2,6 @@
from pypy.translator.c.dlltool import DLLDef
from ctypes import CDLL
import py
-py.test.skip("fix this if needed")
class TestDLLTool(object):
def test_basic(self):
@@ -16,8 +15,8 @@
d = DLLDef('lib', [(f, [int]), (b, [int])])
so = d.compile()
dll = CDLL(str(so))
- assert dll.f(3) == 3
- assert dll.b(10) == 12
+ assert dll.pypy_g_f(3) == 3
+ assert dll.pypy_g_b(10) == 12
def test_split_criteria(self):
def f(x):
@@ -28,4 +27,5 @@
d = DLLDef('lib', [(f, [int]), (b, [int])])
so = d.compile()
- assert py.path.local(so).dirpath().join('implement.c').check()
+ dirpath = py.path.local(so).dirpath()
+ assert dirpath.join('translator_c_test_test_dlltool.c').check()
diff --git a/pypy/translator/driver.py b/pypy/translator/driver.py
--- a/pypy/translator/driver.py
+++ b/pypy/translator/driver.py
@@ -331,6 +331,7 @@
raise Exception("stand-alone program entry point must return an "
"int (and not, e.g., None or always raise an "
"exception).")
+ annotator.complete()
annotator.simplify()
return s
More information about the pypy-commit
mailing list