Author: mattip <matti.pi...@gmail.com> Branch: Changeset: r62318:5929d5aa6cd8 Date: 2013-03-12 08:10 -0700 http://bitbucket.org/pypy/pypy/changeset/5929d5aa6cd8/
Log: merge heads diff --git a/dotviewer/graphclient.py b/dotviewer/graphclient.py --- a/dotviewer/graphclient.py +++ b/dotviewer/graphclient.py @@ -130,10 +130,10 @@ if hasattr(sys, 'pypy_objspaceclass'): # if 'python' is actually PyPy, e.g. in a virtualenv, then # try hard to find a real CPython - for python in ['/usr/local/bin/python', '/usr/bin/python']: - if os.path.exists(python): - break - else: + try: + python = subprocess.check_output( + 'env -i $SHELL -l -c "which python"', shell=True).strip() + except subprocess.CalledProcessError: # did not work, fall back to 'python' python = 'python' else: diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -480,8 +480,6 @@ @_check_thread_wrap @_check_closed_wrap def __call__(self, sql): - if not isinstance(sql, basestring): - raise Warning("SQL is of wrong type. Must be string or unicode.") return self._statement_cache.get(sql, self.row_factory) def cursor(self, factory=None): @@ -878,9 +876,6 @@ if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW: self.__statement._build_row_cast_map() self.__statement._readahead(self) - else: - self.__statement._item = None - self.__statement._exhausted = True if self.__statement._kind == Statement._DML: if self.__rowcount == -1: @@ -1007,7 +1002,7 @@ self.__con = connection if not isinstance(sql, basestring): - raise ValueError("sql must be a string") + raise Warning("SQL is of wrong type. Must be string or unicode.") first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper() if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"): self._kind = Statement._DML @@ -1017,7 +1012,6 @@ self._kind = Statement._DDL self._in_use = False - self._exhausted = False self._row_factory = None if isinstance(sql, unicode): @@ -1055,7 +1049,6 @@ if self._in_use and self._statement: _lib.sqlite3_reset(self._statement) self._in_use = False - self._exhausted = False if sys.version_info[0] < 3: def __check_decodable(self, param): @@ -1220,20 +1213,19 @@ self._item = row def _next(self, cursor): - if self._exhausted: + try: + item = self._item + except AttributeError: raise StopIteration - item = self._item + del self._item ret = _lib.sqlite3_step(self._statement) - if ret == _lib.SQLITE_DONE: - self._exhausted = True - self._item = None - elif ret != _lib.SQLITE_ROW: - exc = self.__con._get_exception(ret) + if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW): _lib.sqlite3_reset(self._statement) - raise exc + raise self.__con._get_exception(ret) + elif ret == _lib.SQLITE_ROW: + self._readahead(cursor) - self._readahead(cursor) return item def _get_description(self): 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 @@ -85,6 +85,8 @@ """Base class for all cpyext tests.""" spaceconfig = dict(usemodules=['cpyext', 'thread', '_rawffi', 'array', 'itertools', 'rctime', 'binascii']) + spaceconfig['std.withmethodcache'] = True + enable_leak_checking = True @staticmethod diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -288,7 +288,38 @@ class C(object): pass assert module.name_by_heaptype(C) == "C" - + + def test_type_dict(self): + foo = self.import_module("foo") + module = self.import_extension('test', [ + ("hack_tp_dict", "METH_O", + ''' + PyTypeObject *type = args->ob_type; + PyObject *a1 = PyLong_FromLong(1); + PyObject *a2 = PyLong_FromLong(2); + PyObject *value; + + if (PyDict_SetItemString(type->tp_dict, "a", + a1) < 0) + return NULL; + Py_DECREF(a1); + PyType_Modified(type); + value = PyObject_GetAttrString(type, "a"); + Py_DECREF(value); + + if (PyDict_SetItemString(type->tp_dict, "a", + a2) < 0) + return NULL; + Py_DECREF(a2); + PyType_Modified(type); + value = PyObject_GetAttrString(type, "a"); + return value; + ''' + ) + ]) + obj = foo.new() + assert module.hack_tp_dict(obj) == 2 + class TestTypes(BaseApiTest): def test_type_attributes(self, space, api): @@ -326,7 +357,7 @@ w_obj = api._PyType_Lookup(w_type, space.wrap("__invalid")) assert w_obj is None assert api.PyErr_Occurred() is None - + class AppTestSlots(AppTestCpythonExtensionBase): def test_some_slots(self): module = self.import_extension('foo', [ diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -729,6 +729,9 @@ subtypes. This function must be called after any manual modification of the attributes or base classes of the type. """ - # PyPy already takes care of direct modifications to type.__dict__ - # (which is a W_DictProxyObject). - pass + # Invalidate the type cache in case of a builtin type. + if not isinstance(w_obj, W_TypeObject): + return + if w_obj.is_cpytype(): + w_obj.mutated(None) + diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -57,11 +57,34 @@ cur = con.cursor() with pytest.raises(StopIteration): next(cur) - cur = con.execute('select 1') + + cur.execute('select 1') next(cur) with pytest.raises(StopIteration): next(cur) + cur.execute('select 1') + con.commit() + next(cur) + with pytest.raises(StopIteration): + next(cur) + + with pytest.raises(_sqlite3.ProgrammingError): + cur.executemany('select 1', []) + with pytest.raises(StopIteration): + next(cur) + + cur.execute('select 1') + cur.execute('create table test(ing)') + with pytest.raises(StopIteration): + next(cur) + + cur.execute('select 1') + cur.execute('insert into test values(1)') + con.commit() + with pytest.raises(StopIteration): + next(cur) + def test_cursor_after_close(): con = _sqlite3.connect(':memory:') cur = con.execute('select 1') diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py --- a/pypy/objspace/std/complexobject.py +++ b/pypy/objspace/std/complexobject.py @@ -9,7 +9,7 @@ from rpython.rlib.rfloat import ( formatd, DTSF_STR_PRECISION, isinf, isnan, copysign) from rpython.rlib import jit, rcomplex -from rpython.rlib.rarithmetic import intmask +from rpython.rlib.rarithmetic import intmask, r_ulonglong import math @@ -41,7 +41,7 @@ real = space.float_w(space.getattr(self, space.wrap("real"))) imag = space.float_w(space.getattr(self, space.wrap("imag"))) real_b = rbigint.fromrarith_int(float2longlong(real)) - imag_b = rbigint.fromrarith_int(float2longlong(imag)) + imag_b = rbigint.fromrarith_int(r_ulonglong(float2longlong(imag))) val = real_b.lshift(64).or_(imag_b).lshift(3).or_(rbigint.fromint(tag)) return space.newlong_from_rbigint(val) diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -106,15 +106,13 @@ for w_k, w_v in list_pairs_w: w_self.setitem(w_k, w_v) - def view_as_kwargs(self): - return self.strategy.view_as_kwargs(self) - def _add_indirections(): dict_methods = "setitem setitem_str getitem \ getitem_str delitem length \ clear w_keys values \ items iterkeys itervalues iteritems setdefault \ - popitem listview_str listview_unicode listview_int".split() + popitem listview_str listview_unicode listview_int \ + view_as_kwargs".split() def make_method(method): def f(self, *args): @@ -122,9 +120,6 @@ f.func_name = method return f - def view_as_kwargs(self): - return self.strategy.view_as_kwargs(self) - for method in dict_methods: setattr(W_DictMultiObject, method, make_method(method)) diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py --- a/pypy/objspace/std/dictproxyobject.py +++ b/pypy/objspace/std/dictproxyobject.py @@ -54,10 +54,11 @@ raise if not w_type.is_cpytype(): raise - # xxx obscure workaround: allow cpyext to write to type->tp_dict - # xxx even in the case of a builtin type. - # xxx like CPython, we assume that this is only done early after - # xxx the type is created, and we don't invalidate any cache. + # Allow cpyext to write to type->tp_dict even in the case + # of a builtin type. + # Like CPython, we assume that this is only done early + # after the type is created, and we don't invalidate any + # cache. User code shoud call PyType_Modified(). w_type.dict_w[key] = w_value def setdefault(self, w_dict, w_key, w_default): @@ -81,7 +82,7 @@ def length(self, w_dict): return len(self.unerase(w_dict.dstorage).dict_w) - def keys(self, w_dict): + def w_keys(self, w_dict): space = self.space return space.newlist_str(self.unerase(w_dict.dstorage).dict_w.keys()) diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py --- a/pypy/objspace/std/test/test_obj.py +++ b/pypy/objspace/std/test/test_obj.py @@ -203,7 +203,9 @@ l.append(i + sys.maxint) l.append(i - sys.maxint) l.append(i + 1j) + l.append(i - 1j) l.append(1 + i * 1j) + l.append(1 - i * 1j) s = str(i) l.append(s) u = unicode(s) diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py --- a/pypy/objspace/std/typeobject.py +++ b/pypy/objspace/std/typeobject.py @@ -161,7 +161,7 @@ generic mutation. """ space = w_self.space - assert w_self.is_heaptype() + assert w_self.is_heaptype() or w_self.is_cpytype() if (not space.config.objspace.std.withtypeversion and not space.config.objspace.std.getattributeshortcut and not space.config.objspace.std.withidentitydict and diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py --- a/rpython/annotator/binaryop.py +++ b/rpython/annotator/binaryop.py @@ -143,13 +143,9 @@ # XXX HACK HACK HACK bk = getbookkeeper() if bk is not None: # for testing + op = bk._find_current_op("is_", 2) knowntypedata = {} - fn, block, i = bk.position_key - annotator = bk.annotator - op = block.operations[i] - assert op.opname == "is_" - assert len(op.args) == 2 def bind(src_obj, tgt_obj, tgt_arg): if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant(): @@ -319,11 +315,7 @@ rarithmetic.signedtype(int2.knowntype)): return r knowntypedata = {} - # XXX HACK HACK HACK - fn, block, i = getbookkeeper().position_key - op = block.operations[i] - assert op.opname == opname - assert len(op.args) == 2 + op = getbookkeeper()._find_current_op(opname=opname, arity=2) def tointtype(int0): if int0.knowntype is bool: return int diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py --- a/rpython/annotator/bookkeeper.py +++ b/rpython/annotator/bookkeeper.py @@ -693,6 +693,20 @@ if emulate_enter: self.leave() + def _find_current_op(self, opname=None, arity=None, pos=None, s_type=None): + """ Find operation that is currently being annotated. Do some + sanity checks to see whether the correct op was found.""" + # XXX XXX HACK HACK HACK + fn, block, i = self.position_key + op = block.operations[i] + if opname is not None: + assert op.opname == opname or op.opname in opname + if arity is not None: + assert len(op.args) == arity + if pos is not None: + assert self.annotator.binding(op.args[pos]) == s_type + return op + def build_args(self, op, args_s): space = RPythonCallsSpace() if op == "simple_call": diff --git a/rpython/annotator/builtin.py b/rpython/annotator/builtin.py --- a/rpython/annotator/builtin.py +++ b/rpython/annotator/builtin.py @@ -178,15 +178,9 @@ # from bool to int, notice that isinstance( , bool|int) # is quite border case for RPython r.const = False - # XXX HACK HACK HACK - # XXX HACK HACK HACK - # XXX HACK HACK HACK bk = getbookkeeper() if variables is None: - fn, block, i = bk.position_key - op = block.operations[i] - assert op.opname == "simple_call" - assert len(op.args) == 3 + op = bk._find_current_op("simple_call", 3) assert op.args[0] == Constant(isinstance) variables = [op.args[1]] for variable in variables: diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py --- a/rpython/annotator/model.py +++ b/rpython/annotator/model.py @@ -233,6 +233,9 @@ def nonnoneify(self): return self.__class__(can_be_None=False, no_nul=self.no_nul) + def nonnulify(self): + return self.__class__(can_be_None=self.can_be_None, no_nul=True) + class SomeString(SomeStringOrUnicode): "Stands for an object which is known to be a string." knowntype = str diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py --- a/rpython/annotator/test/test_annrpython.py +++ b/rpython/annotator/test/test_annrpython.py @@ -446,6 +446,25 @@ s_item = s.listdef.listitem.s_value assert s_item.no_nul + def test_str_split_nul(self): + def f(n): + return n.split('\0')[0] + a = self.RPythonAnnotator() + a.translator.config.translation.check_str_without_nul = True + s = a.build_types(f, [annmodel.SomeString(no_nul=False, can_be_None=False)]) + assert isinstance(s, annmodel.SomeString) + assert not s.can_be_None + assert s.no_nul + + def g(n): + return n.split('\0', 1)[0] + a = self.RPythonAnnotator() + a.translator.config.translation.check_str_without_nul = True + s = a.build_types(g, [annmodel.SomeString(no_nul=False, can_be_None=False)]) + assert isinstance(s, annmodel.SomeString) + assert not s.can_be_None + assert not s.no_nul + def test_str_splitlines(self): a = self.RPythonAnnotator() def f(a_str): @@ -3762,6 +3781,19 @@ assert isinstance(s, annmodel.SomeString) assert not s.can_be_None + def test_contains_no_nul(self): + def f(i): + if "\0" in i: + return None + else: + return i + a = self.RPythonAnnotator() + a.translator.config.translation.check_str_without_nul = True + s = a.build_types(f, [annmodel.SomeString(no_nul=False)]) + assert isinstance(s, annmodel.SomeString) + assert s.can_be_None + assert s.no_nul + def test_no___call__(self): class X(object): def __call__(self): diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -43,12 +43,7 @@ raise Exception, 'type() called with more than one argument' r = SomeType() bk = getbookkeeper() - fn, block, i = bk.position_key - annotator = bk.annotator - op = block.operations[i] - assert op.opname == "type" - assert len(op.args) == 1 - assert annotator.binding(op.args[0]) == obj + op = bk._find_current_op(opname="type", arity=1, pos=0, s_type=obj) r.is_type_of = [op.args[0]] return r @@ -79,10 +74,7 @@ bk = getbookkeeper() knowntypedata = {} - fn, block, i = bk.position_key - op = block.operations[i] - assert op.opname == "is_true" or op.opname == "nonzero" - assert len(op.args) == 1 + op = bk._find_current_op(opname=("is_true", "nonzero"), arity=1) arg = op.args[0] s_nonnone_obj = s_obj if s_obj.can_be_none(): @@ -504,7 +496,11 @@ def method_split(str, patt, max=-1): getbookkeeper().count("str_split", str, patt) - s_item = str.basestringclass(no_nul=str.no_nul) + if max == -1 and patt.is_constant() and patt.const == "\0": + no_nul = True + else: + no_nul = str.no_nul + s_item = str.basestringclass(no_nul=no_nul) return getbookkeeper().newlist(s_item) def method_rsplit(str, patt, max=-1): @@ -520,6 +516,20 @@ result = str.basestringclass(no_nul=str.no_nul) return result + def op_contains(str, s_element): + if s_element.is_constant() and s_element.const == "\0": + r = SomeBool() + bk = getbookkeeper() + op = bk._find_current_op(opname="contains", arity=2, pos=0, s_type=str) + knowntypedata = {} + add_knowntypedata(knowntypedata, False, [op.args[0]], str.nonnulify()) + r.set_knowntypedata(knowntypedata) + return r + else: + return SomeObject.op_contains(str, s_element) + op_contains.can_only_throw = [] + + class __extend__(SomeUnicodeString): def method_encode(uni, s_enc): if not s_enc.is_constant(): _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit