Author: Carl Friedrich Bolz <[email protected]>
Branch: improve-heap-caching-tracing
Changeset: r47067:304d094f3f3c
Date: 2011-09-04 12:31 +0200
http://bitbucket.org/pypy/pypy/changeset/304d094f3f3c/
Log: merge default
diff --git a/lib-python/modified-2.7/sqlite3/test/regression.py
b/lib-python/modified-2.7/sqlite3/test/regression.py
--- a/lib-python/modified-2.7/sqlite3/test/regression.py
+++ b/lib-python/modified-2.7/sqlite3/test/regression.py
@@ -274,6 +274,18 @@
cur.execute("UPDATE foo SET id = 3 WHERE id = 1")
self.assertEqual(cur.description, None)
+ def CheckStatementCache(self):
+ cur = self.con.cursor()
+ cur.execute("CREATE TABLE foo (id INTEGER)")
+ values = [(i,) for i in xrange(5)]
+ cur.executemany("INSERT INTO foo (id) VALUES (?)", values)
+
+ cur.execute("SELECT id FROM foo")
+ self.assertEqual(list(cur), values)
+ self.con.commit()
+ cur.execute("SELECT id FROM foo")
+ self.assertEqual(list(cur), values)
+
def suite():
regression_suite = unittest.makeSuite(RegressionTests, "Check")
return unittest.TestSuite((regression_suite,))
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -54,7 +54,8 @@
def get_ffi_argtype(self):
if self._ffiargtype:
return self._ffiargtype
- return _shape_to_ffi_type(self._ffiargshape)
+ self._ffiargtype = _shape_to_ffi_type(self._ffiargshape)
+ return self._ffiargtype
def _CData_output(self, resbuffer, base=None, index=-1):
#assert isinstance(resbuffer, _rawffi.ArrayInstance)
@@ -225,6 +226,7 @@
'Z' : _ffi.types.void_p,
'X' : _ffi.types.void_p,
'v' : _ffi.types.sshort,
+ '?' : _ffi.types.ubyte,
}
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -293,7 +293,7 @@
#
if stat.in_use:
stat = Statement(self.connection, sql)
- stat.set_cursor_and_factory(cursor, row_factory)
+ stat.set_row_factory(row_factory)
return stat
@@ -705,6 +705,8 @@
from sqlite3.dump import _iterdump
return _iterdump(self)
+DML, DQL, DDL = range(3)
+
class Cursor(object):
def __init__(self, con):
if not isinstance(con, Connection):
@@ -735,9 +737,9 @@
self.statement = self.connection.statement_cache.get(sql, self,
self.row_factory)
if self.connection._isolation_level is not None:
- if self.statement.kind == "DDL":
+ if self.statement.kind == DDL:
self.connection.commit()
- elif self.statement.kind == "DML":
+ elif self.statement.kind == DML:
self.connection._begin()
self.statement.set_params(params)
@@ -748,18 +750,18 @@
self.statement.reset()
raise self.connection._get_exception(ret)
- if self.statement.kind == "DQL"and ret == SQLITE_ROW:
+ if self.statement.kind == DQL and ret == SQLITE_ROW:
self.statement._build_row_cast_map()
- self.statement._readahead()
+ self.statement._readahead(self)
else:
self.statement.item = None
self.statement.exhausted = True
- if self.statement.kind in ("DML", "DDL"):
+ if self.statement.kind == DML or self.statement.kind == DDL:
self.statement.reset()
self.rowcount = -1
- if self.statement.kind == "DML":
+ if self.statement.kind == DML:
self.rowcount = sqlite.sqlite3_changes(self.connection.db)
return self
@@ -771,8 +773,8 @@
sql = sql.encode("utf-8")
self._check_closed()
self.statement = self.connection.statement_cache.get(sql, self,
self.row_factory)
-
- if self.statement.kind == "DML":
+
+ if self.statement.kind == DML:
self.connection._begin()
else:
raise ProgrammingError, "executemany is only for DML statements"
@@ -824,7 +826,7 @@
return self
def __iter__(self):
- return self.statement
+ return iter(self.fetchone, None)
def _check_reset(self):
if self.reset:
@@ -841,7 +843,7 @@
return None
try:
- return self.statement.next()
+ return self.statement.next(self)
except StopIteration:
return None
@@ -855,7 +857,7 @@
if size is None:
size = self.arraysize
lst = []
- for row in self.statement:
+ for row in self:
lst.append(row)
if len(lst) == size:
break
@@ -866,7 +868,7 @@
self._check_reset()
if self.statement is None:
return []
- return list(self.statement)
+ return list(self)
def _getdescription(self):
if self._description is None:
@@ -904,16 +906,15 @@
self.sql = sql # DEBUG ONLY
first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper()
if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
- self.kind = "DML"
+ self.kind = DML
elif first_word in ("SELECT", "PRAGMA"):
- self.kind = "DQL"
+ self.kind = DQL
else:
- self.kind = "DDL"
+ self.kind = DDL
self.exhausted = False
self.in_use = False
#
- # set by set_cursor_and_factory
- self.cur = None
+ # set by set_row_factory
self.row_factory = None
self.statement = c_void_p()
@@ -923,7 +924,7 @@
if ret == SQLITE_OK and self.statement.value is None:
# an empty statement, we work around that, as it's the least
trouble
ret = sqlite.sqlite3_prepare_v2(self.con.db, "select 42", -1,
byref(self.statement), byref(next_char))
- self.kind = "DQL"
+ self.kind = DQL
if ret != SQLITE_OK:
raise self.con._get_exception(ret)
@@ -935,8 +936,7 @@
self._build_row_cast_map()
- def set_cursor_and_factory(self, cur, row_factory):
- self.cur = weakref.ref(cur)
+ def set_row_factory(self, row_factory):
self.row_factory = row_factory
def _build_row_cast_map(self):
@@ -1039,10 +1039,7 @@
raise ProgrammingError("missing parameter '%s'" %param)
self.set_param(idx, param)
- def __iter__(self):
- return self
-
- def next(self):
+ def next(self, cursor):
self.con._check_closed()
self.con._check_thread()
if self.exhausted:
@@ -1058,10 +1055,10 @@
sqlite.sqlite3_reset(self.statement)
raise exc
- self._readahead()
+ self._readahead(cursor)
return item
- def _readahead(self):
+ def _readahead(self, cursor):
self.column_count = sqlite.sqlite3_column_count(self.statement)
row = []
for i in xrange(self.column_count):
@@ -1096,13 +1093,14 @@
row = tuple(row)
if self.row_factory is not None:
- row = self.row_factory(self.cur(), row)
+ row = self.row_factory(cursor, row)
self.item = row
def reset(self):
self.row_cast_map = None
ret = sqlite.sqlite3_reset(self.statement)
self.in_use = False
+ self.exhausted = False
return ret
def finalize(self):
@@ -1118,7 +1116,7 @@
self.statement = None
def _get_description(self):
- if self.kind == "DML":
+ if self.kind == DML:
return None
desc = []
for i in xrange(sqlite.sqlite3_column_count(self.statement)):
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -59,7 +59,12 @@
#
while not target:
if not target.__started:
- _continulet.__init__(target, _greenlet_start, *args)
+ if unbound_method != _continulet.throw:
+ greenlet_func = _greenlet_start
+ else:
+ greenlet_func = _greenlet_throw
+ _continulet.__init__(target, greenlet_func, *args)
+ unbound_method = _continulet.switch
args = ()
target.__started = True
break
@@ -136,3 +141,11 @@
if greenlet.parent is not _tls.main:
_continuation.permute(greenlet, greenlet.parent)
return (res,)
+
+def _greenlet_throw(greenlet, exc, value, tb):
+ _tls.current = greenlet
+ try:
+ raise exc, value, tb
+ finally:
+ if greenlet.parent is not _tls.main:
+ _continuation.permute(greenlet, greenlet.parent)
diff --git a/pypy/interpreter/pyparser/future.py
b/pypy/interpreter/pyparser/future.py
--- a/pypy/interpreter/pyparser/future.py
+++ b/pypy/interpreter/pyparser/future.py
@@ -109,25 +109,19 @@
self.getc() == self.getc(+2)):
self.pos += 3
while 1: # Deal with a triple quoted docstring
- if self.getc() == '\\':
- self.pos += 2
+ c = self.getc()
+ if c == '\\':
+ self.pos += 1
+ self._skip_next_char_from_docstring()
+ elif c != endchar:
+ self._skip_next_char_from_docstring()
else:
- c = self.getc()
- if c != endchar:
- self.pos += 1
- if c == '\n':
- self.atbol()
- elif c == '\r':
- if self.getc() == '\n':
- self.pos += 1
- self.atbol()
- else:
- self.pos += 1
- if (self.getc() == endchar and
- self.getc(+1) == endchar):
- self.pos += 2
- self.consume_empty_line()
- break
+ self.pos += 1
+ if (self.getc() == endchar and
+ self.getc(+1) == endchar):
+ self.pos += 2
+ self.consume_empty_line()
+ break
else: # Deal with a single quoted docstring
self.pos += 1
@@ -138,17 +132,21 @@
self.consume_empty_line()
return
elif c == '\\':
- # Deal with linefeeds
- if self.getc() != '\r':
- self.pos += 1
- else:
- self.pos += 1
- if self.getc() == '\n':
- self.pos += 1
+ self._skip_next_char_from_docstring()
elif c in '\r\n':
# Syntax error
return
+ def _skip_next_char_from_docstring(self):
+ c = self.getc()
+ self.pos += 1
+ if c == '\n':
+ self.atbol()
+ elif c == '\r':
+ if self.getc() == '\n':
+ self.pos += 1
+ self.atbol()
+
def consume_continuation(self):
c = self.getc()
if c in '\n\r':
diff --git a/pypy/interpreter/pyparser/test/test_futureautomaton.py
b/pypy/interpreter/pyparser/test/test_futureautomaton.py
--- a/pypy/interpreter/pyparser/test/test_futureautomaton.py
+++ b/pypy/interpreter/pyparser/test/test_futureautomaton.py
@@ -221,6 +221,14 @@
assert f.lineno == 3
assert f.col_offset == 0
+def test_lots_of_continuation_lines():
+ s = "\\\n\\\n\\\n\\\n\\\n\\\n\nfrom __future__ import with_statement\n"
+ f = run(s)
+ assert f.pos == len(s)
+ assert f.flags == fut.CO_FUTURE_WITH_STATEMENT
+ assert f.lineno == 8
+ assert f.col_offset == 0
+
# This looks like a bug in cpython parser
# and would require extensive modifications
# to future.py in order to emulate the same behaviour
@@ -239,3 +247,19 @@
raise AssertionError('IndentationError not raised')
assert f.lineno == 2
assert f.col_offset == 0
+
+def test_continuation_lines_in_docstring_single_quoted():
+ s = '"\\\n\\\n\\\n\\\n\\\n\\\n"\nfrom __future__ import division\n'
+ f = run(s)
+ assert f.pos == len(s)
+ assert f.flags == fut.CO_FUTURE_DIVISION
+ assert f.lineno == 8
+ assert f.col_offset == 0
+
+def test_continuation_lines_in_docstring_triple_quoted():
+ s = '"""\\\n\\\n\\\n\\\n\\\n\\\n"""\nfrom __future__ import division\n'
+ f = run(s)
+ assert f.pos == len(s)
+ assert f.flags == fut.CO_FUTURE_DIVISION
+ assert f.lineno == 8
+ assert f.col_offset == 0
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -130,8 +130,15 @@
results = _find_jit_marker(graphs, 'jit_merge_point')
if not results:
raise Exception("no jit_merge_point found!")
+ seen = set([graph for graph, block, pos in results])
+ assert len(seen) == len(results), (
+ "found several jit_merge_points in the same graph")
return results
+def locate_jit_merge_point(graph):
+ [(graph, block, pos)] = find_jit_merge_points([graph])
+ return block, pos, block.operations[pos]
+
def find_set_param(graphs):
return _find_jit_marker(graphs, 'set_param')
@@ -235,7 +242,7 @@
def split_graph_and_record_jitdriver(self, graph, block, pos):
op = block.operations[pos]
jd = JitDriverStaticData()
- jd._jit_merge_point_pos = (graph, op)
+ jd._jit_merge_point_in = graph
args = op.args[2:]
s_binding = self.translator.annotator.binding
jd._portal_args_s = [s_binding(v) for v in args]
@@ -504,7 +511,8 @@
self.make_args_specification(jd)
def make_args_specification(self, jd):
- graph, op = jd._jit_merge_point_pos
+ graph = jd._jit_merge_point_in
+ _, _, op = locate_jit_merge_point(graph)
greens_v, reds_v = support.decode_hp_hint_args(op)
ALLARGS = [v.concretetype for v in (greens_v + reds_v)]
jd._green_args_spec = [v.concretetype for v in greens_v]
@@ -552,7 +560,7 @@
assert jitdriver in sublists, \
"can_enter_jit with no matching jit_merge_point"
jd, sublist = sublists[jitdriver]
- origportalgraph = jd._jit_merge_point_pos[0]
+ origportalgraph = jd._jit_merge_point_in
if graph is not origportalgraph:
sublist.append((graph, block, index))
jd.no_loop_header = False
@@ -582,7 +590,7 @@
can_enter_jits = [(jd.portal_graph, jd.portal_graph.startblock, 0)]
for graph, block, index in can_enter_jits:
- if graph is jd._jit_merge_point_pos[0]:
+ if graph is jd._jit_merge_point_in:
continue
op = block.operations[index]
@@ -640,7 +648,7 @@
# while 1:
# more stuff
#
- origportalgraph = jd._jit_merge_point_pos[0]
+ origportalgraph = jd._jit_merge_point_in
portalgraph = jd.portal_graph
PORTALFUNC = jd._PORTAL_FUNCTYPE
@@ -794,14 +802,7 @@
# ____________________________________________________________
# Now mutate origportalgraph to end with a call to portal_runner_ptr
#
- _, op = jd._jit_merge_point_pos
- for origblock in origportalgraph.iterblocks():
- if op in origblock.operations:
- break
- else:
- assert False, "lost the operation %r in the graph %r" % (
- op, origportalgraph)
- origindex = origblock.operations.index(op)
+ origblock, origindex, op = locate_jit_merge_point(origportalgraph)
assert op.opname == 'jit_marker'
assert op.args[0].value == 'jit_merge_point'
greens_v, reds_v = support.decode_hp_hint_args(op)
diff --git a/pypy/module/_continuation/interp_continuation.py
b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -43,11 +43,11 @@
def switch(self, w_to):
to = self.space.interp_w(W_Continulet, w_to, can_be_None=True)
if to is not None:
- if self is to: # double-switch to myself: no-op
- return get_result()
if to.sthread is None:
start_state.clear()
raise geterror(self.space, "continulet not initialized yet")
+ if self is to: # double-switch to myself: no-op
+ return get_result()
if self.sthread is None:
start_state.clear()
raise geterror(self.space, "continulet not initialized yet")
diff --git a/pypy/module/_weakref/interp__weakref.py
b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -8,24 +8,12 @@
class WeakrefLifeline(W_Root):
+ cached_weakref_index = -1
+ cached_proxy_index = -1
+
def __init__(self, space):
self.space = space
self.refs_weak = []
- self.cached_weakref_index = -1
- self.cached_proxy_index = -1
-
- def __del__(self):
- """This runs when the interp-level object goes away, and allows
- its lifeline to go away. The purpose of this is to activate the
- callbacks even if there is no __del__ method on the interp-level
- W_Root subclass implementing the object.
- """
- for i in range(len(self.refs_weak) - 1, -1, -1):
- w_ref = self.refs_weak[i]()
- if w_ref is not None and w_ref.w_callable is not None:
- w_ref.enqueue_for_destruction(self.space,
- W_WeakrefBase.activate_callback,
- 'weakref callback of ')
def clear_all_weakrefs(self):
"""Clear all weakrefs. This is called when an app-level object has
@@ -39,12 +27,11 @@
# weakref callbacks are not invoked eagerly here. They are
# invoked by self.__del__() anyway.
- @jit.dont_look_inside
- def get_or_make_weakref(self, space, w_subtype, w_obj, w_callable):
+ def get_or_make_weakref(self, w_subtype, w_obj):
+ space = self.space
w_weakreftype = space.gettypeobject(W_Weakref.typedef)
is_weakreftype = space.is_w(w_weakreftype, w_subtype)
- can_reuse = space.is_w(w_callable, space.w_None)
- if is_weakreftype and can_reuse and self.cached_weakref_index >= 0:
+ if is_weakreftype and self.cached_weakref_index >= 0:
w_cached = self.refs_weak[self.cached_weakref_index]()
if w_cached is not None:
return w_cached
@@ -52,16 +39,15 @@
self.cached_weakref_index = -1
w_ref = space.allocate_instance(W_Weakref, w_subtype)
index = len(self.refs_weak)
- W_Weakref.__init__(w_ref, space, w_obj, w_callable)
+ W_Weakref.__init__(w_ref, space, w_obj, None)
self.refs_weak.append(weakref.ref(w_ref))
- if is_weakreftype and can_reuse:
+ if is_weakreftype:
self.cached_weakref_index = index
return w_ref
- @jit.dont_look_inside
- def get_or_make_proxy(self, space, w_obj, w_callable):
- can_reuse = space.is_w(w_callable, space.w_None)
- if can_reuse and self.cached_proxy_index >= 0:
+ def get_or_make_proxy(self, w_obj):
+ space = self.space
+ if self.cached_proxy_index >= 0:
w_cached = self.refs_weak[self.cached_proxy_index]()
if w_cached is not None:
return w_cached
@@ -69,12 +55,11 @@
self.cached_proxy_index = -1
index = len(self.refs_weak)
if space.is_true(space.callable(w_obj)):
- w_proxy = W_CallableProxy(space, w_obj, w_callable)
+ w_proxy = W_CallableProxy(space, w_obj, None)
else:
- w_proxy = W_Proxy(space, w_obj, w_callable)
+ w_proxy = W_Proxy(space, w_obj, None)
self.refs_weak.append(weakref.ref(w_proxy))
- if can_reuse:
- self.cached_proxy_index = index
+ self.cached_proxy_index = index
return w_proxy
def get_any_weakref(self, space):
@@ -90,6 +75,45 @@
return w_ref
return space.w_None
+
+class WeakrefLifelineWithCallbacks(WeakrefLifeline):
+
+ def __init__(self, space, oldlifeline=None):
+ self.space = space
+ if oldlifeline is None:
+ self.refs_weak = []
+ else:
+ self.refs_weak = oldlifeline.refs_weak
+
+ def __del__(self):
+ """This runs when the interp-level object goes away, and allows
+ its lifeline to go away. The purpose of this is to activate the
+ callbacks even if there is no __del__ method on the interp-level
+ W_Root subclass implementing the object.
+ """
+ for i in range(len(self.refs_weak) - 1, -1, -1):
+ w_ref = self.refs_weak[i]()
+ if w_ref is not None and w_ref.w_callable is not None:
+ w_ref.enqueue_for_destruction(self.space,
+ W_WeakrefBase.activate_callback,
+ 'weakref callback of ')
+
+ def make_weakref_with_callback(self, w_subtype, w_obj, w_callable):
+ space = self.space
+ w_ref = space.allocate_instance(W_Weakref, w_subtype)
+ W_Weakref.__init__(w_ref, space, w_obj, w_callable)
+ self.refs_weak.append(weakref.ref(w_ref))
+ return w_ref
+
+ def make_proxy_with_callback(self, w_obj, w_callable):
+ space = self.space
+ if space.is_true(space.callable(w_obj)):
+ w_proxy = W_CallableProxy(space, w_obj, w_callable)
+ else:
+ w_proxy = W_Proxy(space, w_obj, w_callable)
+ self.refs_weak.append(weakref.ref(w_proxy))
+ return w_proxy
+
# ____________________________________________________________
class Dummy:
@@ -103,8 +127,7 @@
class W_WeakrefBase(Wrappable):
def __init__(w_self, space, w_obj, w_callable):
- if space.is_w(w_callable, space.w_None):
- w_callable = None
+ assert w_callable is not space.w_None # should be really None
w_self.space = space
assert w_obj is not None
w_self.w_obj_weak = weakref.ref(w_obj)
@@ -177,16 +200,39 @@
def descr__ne__(self, space, w_ref2):
return space.not_(space.eq(self, w_ref2))
+def getlifeline(space, w_obj):
+ lifeline = w_obj.getweakref()
+ if lifeline is None:
+ lifeline = WeakrefLifeline(space)
+ w_obj.setweakref(space, lifeline)
+ return lifeline
+
+def getlifelinewithcallbacks(space, w_obj):
+ lifeline = w_obj.getweakref()
+ if not isinstance(lifeline, WeakrefLifelineWithCallbacks): # or None
+ oldlifeline = lifeline
+ lifeline = WeakrefLifelineWithCallbacks(space, oldlifeline)
+ w_obj.setweakref(space, lifeline)
+ return lifeline
+
[email protected]_look_inside
+def get_or_make_weakref(space, w_subtype, w_obj):
+ return getlifeline(space, w_obj).get_or_make_weakref(w_subtype, w_obj)
+
[email protected]_look_inside
+def make_weakref_with_callback(space, w_subtype, w_obj, w_callable):
+ lifeline = getlifelinewithcallbacks(space, w_obj)
+ return lifeline.make_weakref_with_callback(w_subtype, w_obj, w_callable)
+
def descr__new__weakref(space, w_subtype, w_obj, w_callable=None,
__args__=None):
if __args__.arguments_w:
raise OperationError(space.w_TypeError, space.wrap(
"__new__ expected at most 2 arguments"))
- lifeline = w_obj.getweakref()
- if lifeline is None:
- lifeline = WeakrefLifeline(space)
- w_obj.setweakref(space, lifeline)
- return lifeline.get_or_make_weakref(space, w_subtype, w_obj, w_callable)
+ if space.is_w(w_callable, space.w_None):
+ return get_or_make_weakref(space, w_subtype, w_obj)
+ else:
+ return make_weakref_with_callback(space, w_subtype, w_obj, w_callable)
W_Weakref.typedef = TypeDef("weakref",
__doc__ = """A weak reference to an object 'obj'. A 'callback' can be
given,
@@ -239,15 +285,23 @@
w_obj = force(space, self)
return space.call_args(w_obj, __args__)
[email protected]_look_inside
+def get_or_make_proxy(space, w_obj):
+ return getlifeline(space, w_obj).get_or_make_proxy(w_obj)
+
[email protected]_look_inside
+def make_proxy_with_callback(space, w_obj, w_callable):
+ lifeline = getlifelinewithcallbacks(space, w_obj)
+ return lifeline.make_proxy_with_callback(w_obj, w_callable)
+
def proxy(space, w_obj, w_callable=None):
"""Create a proxy object that weakly references 'obj'.
'callback', if given, is called with the proxy as an argument when 'obj'
is about to be finalized."""
- lifeline = w_obj.getweakref()
- if lifeline is None:
- lifeline = WeakrefLifeline(space)
- w_obj.setweakref(space, lifeline)
- return lifeline.get_or_make_proxy(space, w_obj, w_callable)
+ if space.is_w(w_callable, space.w_None):
+ return get_or_make_proxy(space, w_obj)
+ else:
+ return make_proxy_with_callback(space, w_obj, w_callable)
def descr__new__proxy(space, w_subtype, w_obj, w_callable=None):
raise OperationError(
diff --git a/pypy/module/_weakref/test/test_weakref.py
b/pypy/module/_weakref/test/test_weakref.py
--- a/pypy/module/_weakref/test/test_weakref.py
+++ b/pypy/module/_weakref/test/test_weakref.py
@@ -369,6 +369,26 @@
return A
raises(TypeError, tryit)
+ def test_proxy_to_dead_object(self):
+ import _weakref, gc
+ class A(object):
+ pass
+ p = _weakref.proxy(A())
+ gc.collect()
+ raises(ReferenceError, "p + 1")
+
+ def test_proxy_with_callback(self):
+ import _weakref, gc
+ class A(object):
+ pass
+ a2 = A()
+ def callback(proxy):
+ a2.seen = proxy
+ p = _weakref.proxy(A(), callback)
+ gc.collect()
+ raises(ReferenceError, "p + 1")
+ assert a2.seen is p
+
def test_repr(self):
import _weakref, gc
for kind in ('ref', 'proxy'):
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -8,7 +8,8 @@
modname == '__builtin__.interp_classobj' or
modname == '__builtin__.functional' or
modname == '__builtin__.descriptor' or
- modname == 'thread.os_local'):
+ modname == 'thread.os_local' or
+ modname == 'thread.os_thread'):
return True
if '.' in modname:
modname, _ = modname.split('.', 1)
diff --git a/pypy/module/pypyjit/test/test_policy.py
b/pypy/module/pypyjit/test/test_policy.py
--- a/pypy/module/pypyjit/test/test_policy.py
+++ b/pypy/module/pypyjit/test/test_policy.py
@@ -34,7 +34,9 @@
def test_thread_local():
from pypy.module.thread.os_local import Local
+ from pypy.module.thread.os_thread import get_ident
assert pypypolicy.look_inside_function(Local.getdict.im_func)
+ assert pypypolicy.look_inside_function(get_ident)
def test_pypy_module():
from pypy.module._collections.interp_deque import W_Deque
diff --git a/pypy/module/pypyjit/test_pypy_c/test_globals.py
b/pypy/module/pypyjit/test_pypy_c/test_globals.py
--- a/pypy/module/pypyjit/test_pypy_c/test_globals.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_globals.py
@@ -23,6 +23,4 @@
guard_not_invalidated(descr=...)
p19 = getfield_gc(ConstPtr(p17), descr=<GcPtrFieldDescr
.*W_DictMultiObject.inst_strategy .*>)
guard_value(p19, ConstPtr(ptr20), descr=...)
- p22 = getfield_gc(ConstPtr(ptr21), descr=<GcPtrFieldDescr
.*ModuleCell.inst_w_value .*>)
- guard_nonnull(p22, descr=...)
- """)
+ """)
\ No newline at end of file
diff --git a/pypy/module/pypyjit/test_pypy_c/test_instance.py
b/pypy/module/pypyjit/test_pypy_c/test_instance.py
--- a/pypy/module/pypyjit/test_pypy_c/test_instance.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_instance.py
@@ -181,8 +181,7 @@
assert loop.match_by_id("contains", """
guard_not_invalidated(descr=...)
i11 = force_token()
- i12 = int_add_ovf(i5, i7)
- guard_no_overflow(descr=...)
+ i12 = int_add(i5, 1)
""")
def test_id_compare_optimization(self):
diff --git a/pypy/module/sys/test/test_encoding.py
b/pypy/module/sys/test/test_encoding.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/sys/test/test_encoding.py
@@ -0,0 +1,30 @@
+import os, py
+from pypy.rlib import rlocale
+from pypy.module.sys.interp_encoding import _getfilesystemencoding
+from pypy.module.sys.interp_encoding import base_encoding
+
+
+def test__getfilesystemencoding(space):
+ if not (rlocale.HAVE_LANGINFO and rlocale.CODESET):
+ py.test.skip("requires HAVE_LANGINFO and CODESET")
+
+ def clear():
+ for key in os.environ.keys():
+ if key == 'LANG' or key.startswith('LC_'):
+ del os.environ[key]
+
+ def get(**env):
+ original_env = os.environ.copy()
+ try:
+ clear()
+ os.environ.update(env)
+ return _getfilesystemencoding(space)
+ finally:
+ clear()
+ os.environ.update(original_env)
+
+ assert get() in (base_encoding, 'ANSI_X3.4-1968')
+ assert get(LANG='foobar') in (base_encoding, 'ANSI_X3.4-1968')
+ assert get(LANG='en_US.UTF-8') == 'UTF-8'
+ assert get(LC_ALL='en_US.UTF-8') == 'UTF-8'
+ assert get(LC_CTYPE='en_US.UTF-8') == 'UTF-8'
diff --git a/pypy/module/test_lib_pypy/test_greenlet.py
b/pypy/module/test_lib_pypy/test_greenlet.py
--- a/pypy/module/test_lib_pypy/test_greenlet.py
+++ b/pypy/module/test_lib_pypy/test_greenlet.py
@@ -231,3 +231,13 @@
assert res == "next step"
res = g2.switch("goes to f1 instead")
assert res == "all ok"
+
+ def test_throw_in_not_started_yet(self):
+ from greenlet import greenlet
+ #
+ def f1():
+ never_reached
+ #
+ g1 = greenlet(f1)
+ raises(ValueError, g1.throw, ValueError)
+ assert g1.dead
diff --git a/pypy/module/test_lib_pypy/test_stackless.py
b/pypy/module/test_lib_pypy/test_stackless_pickle.py
rename from pypy/module/test_lib_pypy/test_stackless.py
rename to pypy/module/test_lib_pypy/test_stackless_pickle.py
diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -65,6 +65,10 @@
if isinstance(cell, ModuleCell):
cell.w_value = w_value
return
+ # If the new value and the current value are the same, don't create a
+ # level of indirection, or mutate are version.
+ if self.space.is_w(w_value, cell):
+ return
if cell is not None:
w_value = ModuleCell(w_value)
self.mutated()
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -355,9 +355,13 @@
y = w_float2.floatval
if y == 0.0:
raise FailedToImplementArgs(space.w_ZeroDivisionError,
space.wrap("float modulo"))
- mod = math.fmod(x, y)
- if (mod and ((y < 0.0) != (mod < 0.0))):
- mod += y
+ try:
+ mod = math.fmod(x, y)
+ except ValueError:
+ mod = rfloat.NAN
+ else:
+ if (mod and ((y < 0.0) != (mod < 0.0))):
+ mod += y
return W_FloatObject(mod)
@@ -366,7 +370,10 @@
y = w_float2.floatval
if y == 0.0:
raise FailedToImplementArgs(space.w_ZeroDivisionError,
space.wrap("float modulo"))
- mod = math.fmod(x, y)
+ try:
+ mod = math.fmod(x, y)
+ except ValueError:
+ return [W_FloatObject(rfloat.NAN), W_FloatObject(rfloat.NAN)]
# fmod is typically exact, so vx-mod is *mathematically* an
# exact multiple of wx. But this is fp arithmetic, and fp
# vx - mod is an approximation; the result is that div may
diff --git a/pypy/objspace/std/test/test_celldict.py
b/pypy/objspace/std/test/test_celldict.py
--- a/pypy/objspace/std/test/test_celldict.py
+++ b/pypy/objspace/std/test/test_celldict.py
@@ -39,6 +39,20 @@
assert d.getitem("a") is None
assert d.strategy.getdictvalue_no_unwrapping(d, "a") is None
+ def test_same_key_set_twice(self):
+ strategy = ModuleDictStrategy(space)
+ storage = strategy.get_empty_storage()
+ d = W_DictMultiObject(space, strategy, storage)
+
+ v1 = strategy.version
+ x = object()
+ d.setitem("a", x)
+ v2 = strategy.version
+ assert v1 is not v2
+ d.setitem("a", x)
+ v3 = strategy.version
+ assert v2 is v3
+
class AppTestModuleDict(object):
def setup_class(cls):
cls.space = gettestobjspace(**{"objspace.std.withcelldict": True})
diff --git a/pypy/objspace/std/test/test_floatobject.py
b/pypy/objspace/std/test/test_floatobject.py
--- a/pypy/objspace/std/test/test_floatobject.py
+++ b/pypy/objspace/std/test/test_floatobject.py
@@ -767,3 +767,19 @@
def test_invalid(self):
raises(ValueError, float.fromhex, "0P")
+
+ def test_division_edgecases(self):
+ import math
+
+ # inf
+ inf = float("inf")
+ assert math.isnan(inf % 3)
+ assert math.isnan(inf // 3)
+ x, y = divmod(inf, 3)
+ assert math.isnan(x)
+ assert math.isnan(y)
+
+ # divide by 0
+ raises(ZeroDivisionError, lambda: inf % 0)
+ raises(ZeroDivisionError, lambda: inf // 0)
+ raises(ZeroDivisionError, divmod, inf, 0)
\ No newline at end of file
diff --git a/pypy/objspace/std/test/test_methodcache.py
b/pypy/objspace/std/test/test_methodcache.py
--- a/pypy/objspace/std/test/test_methodcache.py
+++ b/pypy/objspace/std/test/test_methodcache.py
@@ -134,20 +134,24 @@
def test_custom_metaclass(self):
import __pypy__
- class MetaA(type):
- def __getattribute__(self, x):
- return 1
- def f(self):
- return 42
- A = type.__new__(MetaA, "A", (), {"f": f})
- l = [type.__getattribute__(A, "__new__")(A)] * 10
- __pypy__.reset_method_cache_counter()
- for i, a in enumerate(l):
- assert a.f() == 42
- cache_counter = __pypy__.method_cache_counter("f")
- assert cache_counter[0] >= 5
- assert cache_counter[1] >= 1 # should be (27, 3)
- assert sum(cache_counter) == 10
+ for j in range(20):
+ class MetaA(type):
+ def __getattribute__(self, x):
+ return 1
+ def f(self):
+ return 42
+ A = type.__new__(MetaA, "A", (), {"f": f})
+ l = [type.__getattribute__(A, "__new__")(A)] * 10
+ __pypy__.reset_method_cache_counter()
+ for i, a in enumerate(l):
+ assert a.f() == 42
+ cache_counter = __pypy__.method_cache_counter("f")
+ assert sum(cache_counter) == 10
+ if cache_counter == (9, 1):
+ break
+ #else the moon is misaligned, try again
+ else:
+ raise AssertionError("cache_counter = %r" % (cache_counter,))
def test_mutate_class(self):
import __pypy__
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -206,6 +206,7 @@
_immutable_fields_ = ['funcsym']
argtypes = []
restype = lltype.nullptr(clibffi.FFI_TYPE_P.TO)
+ flags = 0
funcsym = lltype.nullptr(rffi.VOIDP.TO)
def __init__(self, name, argtypes, restype, funcsym, flags=FUNCFLAG_CDECL,
diff --git a/pypy/rpython/memory/gc/minimark.py
b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -1461,6 +1461,7 @@
# We will fix such references to point to the copy of the young
# objects when we walk 'old_objects_pointing_to_young'.
self.old_objects_pointing_to_young.append(newobj)
+ _trace_drag_out._always_inline_ = True
def _visit_young_rawmalloced_object(self, obj):
# 'obj' points to a young, raw-malloced object.
diff --git a/pypy/rpython/memory/gctypelayout.py
b/pypy/rpython/memory/gctypelayout.py
--- a/pypy/rpython/memory/gctypelayout.py
+++ b/pypy/rpython/memory/gctypelayout.py
@@ -459,7 +459,7 @@
if t._hints.get('immutable'):
return
if 'immutable_fields' in t._hints:
- skip = t._hints['immutable_fields'].fields
+ skip = t._hints['immutable_fields'].all_immutable_fields()
for n, t2 in t._flds.iteritems():
if isinstance(t2, lltype.Ptr) and t2.TO._gckind == 'gc':
if n not in skip:
diff --git a/pypy/rpython/memory/test/test_gctypelayout.py
b/pypy/rpython/memory/test/test_gctypelayout.py
--- a/pypy/rpython/memory/test/test_gctypelayout.py
+++ b/pypy/rpython/memory/test/test_gctypelayout.py
@@ -4,7 +4,7 @@
from pypy.rpython.memory.gctypelayout import gc_pointers_inside
from pypy.rpython.lltypesystem import lltype, llmemory, rclass
from pypy.rpython.test.test_llinterp import get_interpreter
-from pypy.rpython.rclass import IR_IMMUTABLE
+from pypy.rpython.rclass import IR_IMMUTABLE, IR_QUASIIMMUTABLE
from pypy.objspace.flow.model import Constant
class FakeGC:
@@ -102,7 +102,7 @@
accessor = rclass.FieldListAccessor()
S3 = lltype.GcStruct('S', ('x', PT), ('y', PT),
hints={'immutable_fields': accessor})
- accessor.initialize(S3, {'x': IR_IMMUTABLE})
+ accessor.initialize(S3, {'x': IR_IMMUTABLE, 'y': IR_QUASIIMMUTABLE})
#
s1 = lltype.malloc(S1)
adr = llmemory.cast_ptr_to_adr(s1)
diff --git a/pypy/rpython/rclass.py b/pypy/rpython/rclass.py
--- a/pypy/rpython/rclass.py
+++ b/pypy/rpython/rclass.py
@@ -16,6 +16,13 @@
for x in fields.itervalues():
assert isinstance(x, ImmutableRanking)
+ def all_immutable_fields(self):
+ result = set()
+ for key, value in self.fields.iteritems():
+ if value in (IR_IMMUTABLE, IR_IMMUTABLE_ARRAY):
+ result.add(key)
+ return result
+
def __repr__(self):
return '<FieldListAccessor for %s>' % getattr(self, 'TYPE', '?')
diff --git a/pypy/tool/py.cleanup b/pypy/tool/py.cleanup
--- a/pypy/tool/py.cleanup
+++ b/pypy/tool/py.cleanup
@@ -1,16 +1,31 @@
#!/usr/bin/env python
-import py, sys
+import sys, os, stat
-def shouldremove(p):
- return p.ext == '.pyc'
+def clean(path):
+ global count
+ try:
+ content = os.listdir(path)
+ except OSError:
+ print >> sys.stderr, "skipping", path
+ return
+ for fn in content:
+ filename = os.path.join(path, fn)
+ st = os.lstat(filename)
+ if stat.S_ISDIR(st.st_mode):
+ clean(filename)
+ if fn == '__pycache__':
+ try:
+ os.rmdir(filename)
+ except OSError:
+ pass
+ elif fn.endswith('.pyc') or fn.endswith('.pyo'):
+ os.unlink(filename)
+ count += 1
count = 0
for arg in sys.argv[1:] or ['.']:
- path = py.path.local(arg)
- print "cleaning path", path, "of .pyc files"
- for x in path.visit(shouldremove, lambda x: x.check(dotfile=0, link=0)):
- x.remove()
- count += 1
+ print "cleaning path", arg, "of .pyc/.pyo/__pycache__ files"
+ clean(arg)
print "%d files removed" % (count,)
diff --git a/pypy/translator/goal/app_main.py b/pypy/translator/goal/app_main.py
--- a/pypy/translator/goal/app_main.py
+++ b/pypy/translator/goal/app_main.py
@@ -260,6 +260,8 @@
try:
import _file
except ImportError:
+ if sys.version_info < (2, 7):
+ return
import ctypes # HACK: while running on top of CPython
set_file_encoding = ctypes.pythonapi.PyFile_SetEncodingAndErrors
set_file_encoding.argtypes = [ctypes.py_object, ctypes.c_char_p,
ctypes.c_char_p]
@@ -479,7 +481,8 @@
print >> sys.stderr, "'import site' failed"
readenv = not ignore_environment
- io_encoding = readenv and os.getenv("PYTHONIOENCODING")
+ io_encoding = ((readenv and os.getenv("PYTHONIOENCODING"))
+ or sys.getfilesystemencoding())
if io_encoding:
set_io_encoding(io_encoding)
diff --git a/pypy/translator/goal/test2/test_app_main.py
b/pypy/translator/goal/test2/test_app_main.py
--- a/pypy/translator/goal/test2/test_app_main.py
+++ b/pypy/translator/goal/test2/test_app_main.py
@@ -739,6 +739,19 @@
data = self.run(p + os.sep)
assert data == p + os.sep + '\n'
+ def test_getfilesystemencoding(self):
+ if sys.version_info < (2, 7):
+ skip("test requires Python >= 2.7")
+ p = getscript_in_dir("""
+ import sys
+ sys.stdout.write(u'15\u20ac')
+ sys.stdout.flush()
+ """)
+ env = os.environ.copy()
+ env["LC_CTYPE"] = 'en_US.UTF-8'
+ data = self.run(p, env=env)
+ assert data == '15\xe2\x82\xac'
+
def test_pythonioencoding(self):
if sys.version_info < (2, 7):
skip("test requires Python >= 2.7")
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit